Jump to content

Robin S

Members
  • Posts

    4,791
  • Joined

  • Days Won

    303

Posts posted by Robin S

  1. 1 hour ago, Jim Bailie said:

    I wonder if I can drop the upload name into a template field so the admins have a visual frame of reference on the admin screen.

    The upload name is shown in a tooltip when you hover on the file icon in the inputfield:

    image.png.67c4a9954eea0ebfa42bca065abf6889.png

    If you want something that's always visible you could hook into the inputfield rendering:

    // Display upload name in InputfieldFile
    $wire->addHookAfter('InputfieldFile::renderItem', function(HookEvent $event) {
    	/** @var Pagefile $pagefile */
    	$pagefile = $event->arguments(0);
    	$event->return = "<p class='upload-name'>$pagefile->uploadName</p>" . $event->return;
    });

    And then style it with some custom admin CSS:

    .InputfieldFileItem .upload-name { color:white; line-height:1.33; padding:6px 10px; margin:0; background-color:#606060; }

    There are several ways you can add custom CSS to the PW admin - here is one:

    // Add custom CSS to admin
    $wire->addHookAfter('AdminTheme::getExtraMarkup', function(HookEvent $event) {
    	$config = $event->wire()->config;
    	$parts = $event->return;
    	$css_url = $config->urls->templates . 'admin-assets/admin-custom.css';
    	$modified = filemtime(rtrim($config->paths->root, '/') . $css_url);
    	$parts['head'] .= "<link rel='stylesheet' href='$css_url?m=$modified'>";
    	$event->return = $parts;
    });

    Result:

    image.png.57034bc4ccd1154a1c92c002eeebfb50.png

    • Like 5
    • Thanks 1
  2. 1 hour ago, Jim Bailie said:

    Well pdf files with a '$' don't migrate so well into PW. In fact, they don't migrate at all.

    Could you give more details about what you mean by this? Are you trying to import files via the API and this fails somehow? Or you mean that the $ character is not retained in the filename after you add the file to a Files field?

    If it's the latter I wrote a tutorial you might find useful:

     

    • Like 1
  3. ProcessWire automatically sanitises the names of files that are uploaded to a Files field. For example, a file named "Café meals under $30.pdf" will become "cafe_meals_under_30.pdf" after it is uploaded.

    Since v3.0.212 ProcessWire stores the original unsanitised filename of each uploaded file, and this is accessible via $pagefile->uploadName
    https://processwire.com/blog/posts/pw-3.0.226/#file-and-image-improvements
    https://processwire.com/api/ref/pagefile/upload-name/

    So if I have a field named "files" on my page and I want to provide downloads of the files with their original filename I can output links like this:

    $out = '';
    foreach($page->files as $file) {
        // uploadName is entity-encoded when output formatting is on
        $original_name_unencoded = html_entity_decode($file->uploadName);
        $out .= "<p><a href='$file->url' download='$original_name_unencoded'>$file->uploadName</a></p>";
    }
    echo $out;

    So far, so good. But I want my site visitors to be able to view PDFs in the browser rather than force a download, yet if they do download them after viewing them I want the files to get the original filename. For this I can use a URL hook to deliver the PDF via PHP rather than directly loading the file.

    In /site/ready.php:

    $wire->addHook('/view-pdf/{page_id}/{filename}', function($event) {
    	$id = (int) $event->page_id;
    	$filename = $event->wire()->sanitizer->text($event->filename);
    	if(!$id || !$filename) return 'Invalid request';
    	// Get the Pagefile via PagefilesManager
    	$pm = $event->wire()->pages->get($id)->filesManager;
    	$file = $pm->getFile($filename);
    	if(!$file) return 'File not found';
    
    	// uploadName is entity-encoded when output formatting is on
    	$original_name_unencoded = html_entity_decode($file->uploadName);
    	// Set headers and output the PDF content
    	header("Content-Type: application/pdf");
    	header("Content-Disposition: inline; filename=$original_name_unencoded");
    	header("Content-Transfer-Encoding: binary");
    	header("Accept-Ranges: bytes");
    	@readfile($file->filename);
    	return true;
    });

    In the page template file:

    $out = '';
    foreach($page->files as $file) {
        if($file->ext === 'pdf') {
            // Deliver PDF files via the URL hook
            $out .= "<p><a href='/view-pdf/$page->id/$file->basename'>$file->uploadName</a></p>";
        } else {
            // Other files receive a download attribute
            // uploadName is entity-encoded when output formatting is on
            $original_name_unencoded = html_entity_decode($file->uploadName);
            $out .= "<p><a href='$file->url' download='$original_name_unencoded'>$file->uploadName</a></p>";
        }
    }
    echo $out;

     

    • Like 14
    • Thanks 1
  4. 17 hours ago, herr rilke said:
    foreach ($page->pagetable as $pt) {

    In this code, $pt is already a Page object so you don't need to get it again from $pages. You can just call the render method on it directly.

    foreach($page->pagetable as $pt) {
    	$content .= $pt->render();
    }

     

    17 hours ago, herr rilke said:

    but still not to easy to set up a page with sections and all that

    For this sort of thing you'll find that Repeater Matrix is money well spent.
    https://processwire.com/store/pro-fields/repeater-matrix/

  5. 38 minutes ago, Flashmaster82 said:

    If i add a webp image url i get error "Pageimage: johnrogershousemay2020.0x260.webp - not a supported image type"... ? Any idea whats wrong?

    The core InputfieldImage does not support webp format.

  6. Field Initial Value

    For most field types, allows the definition of an initial value that is automatically set when pages are created.

    The initial value can be set in template context if you want a different initial value in different templates.

    Example for a "Countries" Page Reference field using AsmSelect:

    initial-value-1

    Example with explanatory notes in a CKEditor field:

    initial-value-2

    Differences from "Default value"

    The core allows setting a "Default value" for certain field types. The "Initial value" setting added by this module is different from the "Default value" setting in the following ways:

    1. The "Default value" is a setting that applies only to the inputfield, meaning that the value is shown in the inputfield by default but is not stored until you save the page. By contrast, the "Initial value" is automatically saved to the page when the page is first created.
    2. Related to point 1, when a page is created via the API rather than in the ProcessWire admin the "Initial value" is saved to the page but the "Default value" is not.
    3. The "Default value" has no effect when a field is not "required", but the "Initial value" is set for both required and not required fields.
    4. Related to point 3, a user can empty a field that had an "Initial value" applied but a field with a "Default value" set cannot be emptied.
    5. The "Initial value" setting is available for more field types than "Default value".

    Supported field types

    The following field types are supported, along with any types that extend them:

    • FieldtypeText (includes types that extend it such as Textarea, CKEditor, URL, etc.)
    • FieldtypeDatetime
    • FieldtypeInteger
    • FieldtypeDecimal
    • FieldtypeFloat
    • FieldtypePage (with all core inputfield types)
    • FieldtypeCheckbox
    • FieldtypeOptions (with all core inputfield types)
    • FieldtypeToggle
    • FieldtypeSelector
    • FieldtypeMultiplier (ProField)
    • FieldtypeCombo (ProField, only supported when File and Image subfields are not used)
    • FieldtypeStars (third-party module)

    If you want to try field types beyond this you can define additional types in the module config, but your mileage may vary.

    Unsupported field types

    It's not possible to set an initial value for these field types, along with any types that extend them:

    • FieldtypeFile (and FieldtypeImage)
    • FieldtypeRepeater (includes types that extend it such as Repeater Matrix and Fieldset Page)
    • FieldtypePageTable
    • FieldtypeTable (ProField)

    Notes

    Seeing as the initial value is defined in the field config it has no idea of the current page - for the purposes of rendering the initial value inputfield the home page is supplied as a dummy page. This probably isn't an issue in most cases but it might have an effect for some Page Reference fields if they use the current page to limit the selectable pages.

     

    https://github.com/Toutouwai/FieldInitialValue
    https://processwire.com/modules/field-initial-value/

    • Like 12
    • Thanks 3
  7. 16 hours ago, msavard said:

    Could you give a more complete example of how to use this on the front end?

    This is a ProcessWire Fieldtype/Inputfield module so use on the frontend isn't something that's supported directly. If you have FormBuilder then the readme explains how to enable InputfieldStars for FormBuilder.

    If you are using the PW forms API for the frontend then it's really beyond the scope of this module support topic, but you can refer to forum topics like this:

    Essentially you would do something like this:

    /** @var InputfieldForm $form */
    $form = $modules->get('InputfieldForm');
    
    /** @var InputfieldStars $f */
    $f = $modules->get('InputfieldStars');
    $f->name = 'stars';
    $f->label = 'Stars';
    $form->add($f);
    
    echo $form->render();

    Plus seeing as you are outside the PW admin the inputfield-specific JS and CSS are not going to be automatically included so you'll need to add them to your template file manually:

    <link href="/site/modules/FieldtypeStars/InputfieldStars.css" rel="stylesheet">
    <script src="/site/modules/FieldtypeStars/rater-js/rater-js.js"></script>
    <script src="/site/modules/FieldtypeStars/InputfieldStars.js"></script>

     

    • Like 2
  8. @ShadowByte first let me say welcome to the PW forums 🙂

    13 hours ago, ShadowByte said:

    Is it possible that this doesn't work with a Repeater?

    The module does work with repeaters, but perhaps not in the way you are expecting. If you are relatively new to PW you may not be aware that every repeater item is a page, and those repeater pages have their own template. Repeater template names take the form "repeater_[field name]" and to see them in the templates list you have to enable "Show system templates" in the Filters section.

    image.png.1d047678c6fc55a899360a48d17d5ffe.png

    The Connect Page Fields readme says:

    Quote

    Make sure you have set the "Selectable Pages" settings for each Page field correctly:

    • The settings for Page field A should allow pages using the template(s) that Page field B has been added to.
    • The settings for Page field B should allow pages using the template(s) that Page field A has been added to.

    The way you have configured the module you have connected the fields "Track lyric" and "Albums". But the Albums field allows pages using the album template, and the album template doesn't contain the lyric field. Instead the lyric field is used on the repeater template (if the repeater field is named "tracks" then the template will be "repeater_tracks").

    So for Connect Page Fields to work you would need to have a Page Reference field that defines its selectable pages as those using the repeater_tracks template and then connect that field to the lyric field in the Connect Page Fields config.

    As a side note, it's redundant to double up the connections like this in the module config:

    13 hours ago, ShadowByte said:

    Module Connect Page Fields.png

    The connections are two-way so you only need to link a Page Reference field to its partner once.

    Assuming you actually want to connect albums to lyrics and not repeater_tracks items to lyrics, and you want to still use Connect Page Fields to avoid writing your own API code to synchonise the Page Reference fields, here's how I would do it...

    1. Create a new Page Reference field (multiple pages) named "track_lyrics" that allows pages with the lyric template.

    2. Add this field to the album template. Later on you might set its visibility to "Hidden (not shown in editor)" but for now leave it visible so you can check that everything works as expected.

    3. In the Connect Page Fields config, connect the albums field to the track_lyrics field. 

    4. Add a Pages::saveReady() hook to /site/ready.php that will populate the track_lyrics field with all the lyrics that have been selected inside the repeater items on the page, every time an album page is saved. It might look something like this (update the template/field names if needed):

    $pages->addHookAfter('saveReady', function(HookEvent $event) {
    	/** @var Page $page */
    	$page = $event->arguments(0);
    
    	// Album: populate the track_lyrics field from the "tracks" repeater items
    	if($page->template == 'album') {
    		$lyrics = new PageArray();
    		foreach($page->tracks as $track) {
    			$lyrics->add($track->lyric);
    		}
    		$page->track_lyrics = $lyrics;
    	}
    });

    Hope this helps!

    • Like 3
  9. 19 hours ago, fruid said:

    Because as I understand it, the value needs to change and the page needs to be saved for the module to do what it does.

    Correct.

    19 hours ago, fruid said:

    Doesn't work though…

    Don't know, similar code works for me here. Trying to set a plain WireArray to a Page Reference field looks wrong to me. The acceptable value to set to a Page Reference field is a Page or PageArray.

    There is some example code in the post below that can help deal with Page Reference field values from before the module was installed:

     

     

    • Like 1
  10. On 6/28/2023 at 1:33 AM, teppo said:

    First of all, there are other benefits than performance — such as the fancy process view that SessionHandlerDB comes with (if I recall correctly, it's been a long time since I've tried it).

    For anyone interested, I've released a module that provides information about active sessions similar to SessionHandlerDB, but for file-based sessions:

     

    • Like 5
×
×
  • Create New...