Jump to content

Robin S

Members
  • Posts

    4,928
  • Joined

  • Days Won

    321

Everything posted by Robin S

  1. And page 1017 references page 1018, right? It's a circular reference issue that seems to happen when two pages that reference each other are both loaded into memory. Probably connected to this issue: https://github.com/processwire/processwire-issues/issues/572
  2. Looks like that code needs a change to account for "single" Page Reference fields: // Get all pages where page_field_a is not empty $pgs = $pages->find("page_field_a.count>0"); // Get derefAsPage property of page_field_b to distinguish multiple/single page fields $deref = $fields->get('page_field_b')->derefAsPage; foreach($pgs as $p) { // For this page, get the pages selected in page_field_a $selected_pages = $p->page_field_a; // Standardise $selected_pages to PageArray in case of "single" field if($selected_pages instanceof Page) $selected_pages = $selected_pages->and(); foreach($selected_pages as $selected_page) { // Add this page to page_field_b on the selected page $selected_page->of(false); if($deref) { $selected_page->page_field_b = $p; } else { $selected_page->page_field_b->add($p); } $selected_page->save(); } } I don't fully understand what you're asking here, but in general you can switch "page_field_a" and "page_field_b" and run the code again if you need to. Of course make a DB backup before running any bulk API action in case something unexpected happens.
  3. No particular reason as far as I remember - probably I was just trying different things and stopped as soon as I found a way to get the job done. Usually in PW there are several different way to achieve any goal.
  4. There's a bit more more work needed before my module could be released publicly but I'll put it on my "to do" list. Yes, but in my use cases that's a good thing. This approach only suits certain types of search needs, where you want to implement a broad text search across most/all content. In my cases I want the search to match as many pages as possible, so I do things like explode the search phrase on space characters and then match each term with the %= LIKE operator so I'm catching part words too and without regard to the order of terms: $search_terms = $sanitizer->selectorValue($input->get->search); $search_terms = preg_replace("/\s+/", " ", $search_terms); // replace multiple spaces with single space $terms = explode(' ', $search_terms); foreach($terms as $term) { $selector .= "index%=$term, "; } //... And I want the excerpt to be Google-like in that it deals with the page's text content as a whole rather than caring about what fields were used behind the scenes.
  5. File Info A textformatter module for ProcessWire. The module can add information to local Pagefile links in two ways: As extra markup before, within or after the link As data attributes on the link (handy if you want to use a Javascript tooltip library, for instance) Screenshots Module config Example of output Installation Install the File Info module. Add the textformatter to one or more CKEditor fields. Configuration Add markup action (and general) Select "Add markup to links" Select the Pagefile attributes that will be retrieved. The attribute "filesizeStrCustom" is similar to the core "filesizeStr" attribute but allows for setting a custom number of decimal places. If you select the "modified" or "created" attributes then you can define a date format for the value. Enter a class string to add to the links if needed. Define the markup that will be added to the links. Surround Pagefile attribute names in {brackets}. Attributes must be selected in the "Pagefile attributes" section in order to be available in the added markup. If you want include a space character at the start or end of the markup then you'll need >= PW 3.0.128. Select where the markup should be added: prepended or appended within the link, before the link, or after the link. Add data attributes action Select "Add data attributes to links" Select the Pagefile attributes that will be retrieved. These attributes will be added to the file links as data attributes. Attributes with camelcase names will be converted to data attribute names that are all lowercase, i.e. filesizeStrCustom becomes data-filesizestrcustom. Hook If you want to customise or add to the attributes that are retrieved from the Pagefile you can hook TextformatterFileInfo::getFileAttributes(). For example: $wire->addHookAfter('TextformatterFileInfo::getFileAttributes', function(HookEvent $event) { $pagefile = $event->arguments(0); $page = $event->arguments(1); $field = $event->arguments(2); $attributes = $event->return; // Add a new attribute $attributes['sizeNote'] = $pagefile->filesize > 10000000 ? 'This file is pretty big' : 'This file is not so big'; $event->return = $attributes; }); https://github.com/Toutouwai/TextformatterFileInfo https://modules.processwire.com/modules/textformatter-file-info/
  6. As per the last comment in the linked thread, my approach is to use a Pages::saveReady hook save all text content on each page to a hidden "index" field in the template. Then there is just a single field to search and pull excerpts from. I have a module that I'll get around to releasing one of these days, but the basic idea is that in the saveReady hook you loop over all fields in the page, get the text content from the field depending on field type (e.g. strip markup from CKEditor fields, get descriptions from an images field, loop over subfields in a Repeater/PageTable, etc) and save that to the index field.
  7. The TfaTotp module is not a core module so it won't be covered in the core docs. The base Tfa class is in the API docs here: https://processwire.com/api/ref/tfa/ There's no tutorial AFAIK but you can refer to the implementation in ProcessLogin and there is a basic usage example given in the comments for Tfa.php: * USAGE * ~~~~~~ * $tfa = new Tfa(); * * if($tfa->success()) { * $session->redirect('after/login/url/'); * * } else if($tfa->active()) { * echo $tfa->render(); * * } else if($input->post('submit_login')) { * $name = $input->post('name'); * $pass = $input->post('pass'); * $tfa->start($name, $pass); * * // the start() method performs a redirect if TFA is active for the user * // place your regular code to login user here, which will be used if TFA is not active for the user * * } else { * // render login form * } Also see the introductory blog post for info about how the TFA selection field is added to the user template: https://processwire.com/blog/posts/processwire-3.0.109-adds-two-factor-authentication/
  8. @ngrmm, you can do this by not defining a parent for selectable pages in the field settings (just define a template) and add the following in /site/ready.php: $wire->addHookBefore('InputfieldPage::renderAddable', null, 'setAddParent'); $wire->addHookBefore('InputfieldPage::processInputAddPages', null, 'setAddParent'); function setAddParent(HookEvent $event) { $inputfield = $event->object; // Only for this one Page Reference field if($inputfield->hasField != 'tags') return; // Only for ProcessPageEdit if($event->wire('process') != 'ProcessPageEdit') return; // Set the ID of the parent page that new pages should be added under $inputfield->parent_id = 1234; }
  9. Yeah, these view links are not helpful IMO. Related request: https://github.com/processwire/processwire-requests/issues/274 Edit: just noticed that you already thumbs-upped that. ?
  10. Not with the module itself because to hide or show something in your template would require logic within the template file. But you could use a similar approach to that used in the module. In the template you would check if the user has the necessary role, or if a GET variable containing some password is present, and if so you show the extra content. I don't have any ideas regarding the limited editing though. I don't think you could (or should try to) override the PW admin access controls using just a query string. In the past if I needed to show a client the edit interface for a site before it was ready I just showed them a screenshot or a screencast.
  11. Are you sure? Page Path History seems to correctly redirect pages after I move a page structure in Page List.
  12. @ethanbeyer, no worries, just glad to help. ? It would be good to get to the bottom of what is causing ImageMagick to suddenly fail though. @netcarver linked to this article recently in another topic: https://alexvanderbist.com/posts/2018/fixing-imagick-error-unauthorized It deals with a new security policy relating to PDF conversion but I wonder if some other policy has been introduced that affects JPGs too. If so there might need to be a fix applied to ImageSizerEngineImagick. Maybe your host could shed some light on what policy is being triggered by your uploads? Or maybe @horst has heard something about an ImageMagick update that might be connected?
  13. I don't think this has anything to do with the home page specifically - it's the 404 page, which gets markup from _main.php because I expect that file is auto-appended to the template. My suspicion is that some security policy on your server is interfering to block the normal PW behaviour, and the 404 is a side-effect. It looks like ModSecurity is not enabled though so perhaps something else. You could ask your hosting provider to check. Are you using ImageSizerEngineImagick by any chance? Does the issue resolve if you uninstall that to use the GD default?
  14. So serve the original rather than a variation then. It's totally up to you and what you write in your template code - PW doesn't compel you to load anything on the front-end.
  15. Your selector would go something like: $properties = $pages->find("template=property, pstatus=''|sold, sort=pstatus, sort=price"); This works because when you sort by the value of pstatus an empty value will sort before any other value. Which is fine in this case because you happen to want the pages with empty pstatus (available properties) to sort first. But you actually get more complete control of sort order if you create a status page for "available", make the pstatus field required, and set the default value of pstatus to "available". That way you can set the sort position of the "available" page to some other position than first if you happen to need to change to that at some time in the future. Then in your selector you can sort by the sort value of the status page selected in the pstatus field. So if you needed to find properties with statuses "available", "sold" and "paused" and the sort order of those status pages in the tree is "paused", "available", "sold" then your results would get that same sort order with this selector: $properties = $pages->find("template=property, pstatus=available|sold|paused, sort=pstatus.sort");
  16. If you load an admin page in a modal or panel from the front-end then there's not really any special PW magic there - it's just an iframe. So you don't have to use a JqueryUI modal or panel just because the PW admin does - you can use any JS modal library that supports iframes. There are a bazillion out there so there's bound to be something that doesn't cause this scrolling issue you're describing. BTW I can confirm the tree panel scrolling issue on iPad - please do report it.
  17. You don't need to migrate to a new hosting server just because the domain name for a site changes. Point the domain to your host and update $config->httpHosts in /site/config.php. Depending on the type of hosting you might need to adjust a setting there too, e.g. update the primary domain if it's a cPanel host.
  18. v0.1.2 released - this update allows the 404 page markup to be replaced.
  19. I'll look at adding something like this in a future update. Although most devs will already be using a password manager and these usually come with a generator built in. There are lots of different things that users might want to do with the replacement markup - too many to support with dedicated options in the config. That's the reason behind the hookable method. I've just pushed an update that passes the title and message as arguments to the method, so you can do something like this: $wire->addHookBefore('AccessByQueryString::replacementMarkup', function(HookEvent $event) { $message = $event->arguments(3); // Convert markdown to HTML $message = $event->wire('sanitizer')->entitiesMarkdown($message); // Alternatively use a textformatter // $event->wire('modules')->TextformatterMarkdownExtra->format($message); $event->arguments(3, $message); });
  20. This feature is only available to superusers. See the blog post that introduced it: https://processwire.com/blog/posts/processwire-3.0.118-core-updates/#new-redirect-url-management-in-the-page-editor If the setting of redirect URLs is just a temporary need while the site is being migrated you could edit the relevant lines of the ProcessPageEdit module. Or copy the module folder to /site/modules/ and make the change there. E.g. // page path history (previous URLs) if($superuser || $this->wire('user')->hasRole('editor')) { $f = $this->buildFormPrevPaths(); if($f) $wrapper->add($f); } But you wouldn't want to leave this in place long term because it will mean you won't get core fixes or upgrades to ProcessPageEdit.
  21. The syntax works for me to match pages with multiple options selected: Do you have values and titles defined separately for your Options field? If so you probably want to include the subfield in your selector: category.title or category.value
  22. Access By Query String Grant/deny access to pages according to query string. Allows visitors to view protected pages by accessing the page via a special URL containing an "access" GET variable. This allows you to provide a link to selected individuals while keeping the page(s) non-viewable to the public and search engines. The recipients of the link do not need to log in so it's very convenient for them. The view protection does not provide a high level of security so should only be used for non-critical scenarios. The purpose of the module was to prevent new websites being publicly accessible before they are officially launched, hence the default message in the module config. But it could be used for selected pages on existing websites also. Once a visitor has successfully accessed a protected page via the GET variable then they can view any other page protected by the same access rule without needing the GET variable for that browsing session. Superusers are not affected by the module. Usage Install the Access By Query String module. Define access rules in the format [GET variable]??[selector], one per line. As an example the rule... rumpelstiltskin??template=skills, title~=gold ...means that any pages using the "skills" template with the word "gold" in the title will not be viewable unless it is accessed with ?access=rumpelstiltskin in the URL. So you could provide a view link like https://domain.com/skills/spin-straw-into-gold/?access=rumpelstiltskin to selected individuals. Or you could limit view access to the whole frontend with a rule like... 4fU4ns7ZWXar??template!=admin You can choose what happens when a protected page is visited without the required GET variable: Replace the rendered markup Throw a 404 exception If replacing the rendered markup you can define a meta title and message to be shown. Or if you want to use more advanced markup you can hook AccessByQueryString::replacementMarkup(). $wire->addHookAfter('AccessByQueryString::replacementMarkup', function(HookEvent $event) { // Some info in hook arguments if needed... // The page that the visitor is trying to access $page = $event->arguments(0); // An array of access keys that apply to the page $access_keys = $event->arguments(1); // The title $title = $event->arguments(2); // The message $message = $event->arguments(3); // Return some markup $event->return = 'Your markup'; }); Screenshot https://github.com/Toutouwai/AccessByQueryString https://modules.processwire.com/modules/access-by-query-string/
  23. Another way via a hook in /site/ready.php: $wire->addHookBefore('ProcessPageLister::execute', function(HookEvent $event) { // Only for main "Find" lister if($event->wire('page')->name !== 'lister') return; $lister = $event->object; $lister->allowSystem = true; }); This (and @adrian's suggestion) will only work for superusers because non-superusers are not allowed to view user pages.
  24. You can use a full path to the file rather than a relative one. I think it's a good practice to do this for all includes as it's more robust than a relative path. If you get tired of typing $config->paths->templates you can do something like define a shorter constant/variable in an auto-prepended _init.php, or just a shorter version in config.php, eg. $config->tp
  25. I think you could achieve this using PHP logic without any special file system needed. I haven't used WordPress but from the docs you linked to it sounds like any existing child template replaces the parent template of the same. This would be easy to achieve in PW. The following examples assume a Markup Regions approach to templating. Your parent template files go in /site/templates/: _main.php basic-page.php home.php Your child template files go in /site/templates/child-templates/. You only create files for templates that you want to be different from the parent templates. Likewise for _main.php if you want to change that in your child theme. child-templates/_main.php child-templates/basic-page.php In /site/ready.php: $wire->addHookBefore('Page::render', function(HookEvent $event) { $page = $event->object; $templates_path = $event->wire('config')->paths->templates; // See if a replacement template file exists in child-templates $alt_template_path = "{$templates_path}child-templates/{$page->template->name}.php"; if(is_file($alt_template_path)) { // If so, use it as the template file $page->template->filename = $alt_template_path; } // See if a replacement _main.php file exists in child-templates if(is_file("{$templates_path}child-templates/_main.php")) { // If so, disable the default _main.php and use the replacement $page->template->noAppendTemplateFile = true; $page->template->appendFile = 'child-templates/_main.php'; } }); So that would cover template replacement as per WordPress (if I understand it right). But with Markup Regions it would be nice to have the option to sort of "extend" an existing template file rather than replace it. You could do this by putting files in /site/templates/child-templates/ with an "_append" suffix. The contents of these files gets included after the markup of the parent template of the same name, so you could use Markup Regions features like pw-append, pw-before, etc, to add to the markup of the parent template. child-templates/home_append.php And at the top of your _main.php file before the DOCTYPE (and same with child-templates/_main.php if you are using that): <?php // See if an append template file exists in child-templates $append_template_path = "{$config->paths->templates}child-templates/{$page->template->name}_append.php"; // If so, include it if(is_file($append_template_path)) include $append_template_path; ?>
×
×
  • Create New...