Jump to content

Robin S

Members
  • Posts

    5,039
  • Joined

  • Days Won

    340

Everything posted by Robin S

  1. 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.
  2. v0.1.2 released - this update allows the 404 page markup to be replaced.
  3. 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); });
  4. 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.
  5. 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
  6. 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/
  7. 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.
  8. 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
  9. 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; ?>
  10. You can use a hook like this in /site/ready.php: $wire->addHookBefore('InputfieldPageAutocomplete(name=link_page_url)::render', function(HookEvent $event) { $inputfield = $event->object; // Get the page being edited $page_id = $event->wire('input')->get->int('id'); $edited_page = $event->wire('pages')->get($page_id); // If the edited page is one that you want to target if($edited_page->template == 'basic_page') { // Append to the findPagesSelector property to exclude pages you don't want to match $inputfield->findPagesSelector .= ', has_parent!=/menus/'; } });
  11. Also see $page->rootParent if($page->rootParent->id === 1116) { echo "My conditional content"; }
  12. Seems like a bug, or something that should be documented if "parent" is a special case for selectors. I opened a GitHub issue: https://github.com/processwire/processwire-issues/issues/838 As an alternative you can use OR-groups: $pages->find("(id=$page), (parent=$page)")
  13. You can install the predefined page-publish system permission: https://processwire.com/docs/user-access/permissions/#page-publish Then do not give the role that permission for the template of the page in question.
  14. It seems that the user needs to have the page-edit permission for both the parent page and the child page in order to sort the child page. I hadn't noticed this before. It's a shame that the page-sort permission can't be granted independently of page-edit as it seems like they involve quite different levels of risk/responsibility. I opened a request at GitHub: https://github.com/processwire/processwire-requests/issues/290 As for a hook you could use this in/site/ready.php: // Just for your target role if($user->hasRole('editor')) { $wire->addHookAfter('ProcessPageEdit::execute', function(HookEvent $event) { /* @var ProcessPageEdit $ppe */ $ppe = $event->object; $page = $ppe->getPage(); // The names of templates that the user is not allowed to edit $disallowed_templates = ['colours', 'colour']; if(in_array($page->template->name, $disallowed_templates)) { // Replace the Page Edit markup $event->return = 'You do not have permission to edit this page.'; } }); } This may not be 100% secure in that a person could theoretically create their own edit form in their browser dev tools (although I think that's a very unlikely possibility). But if you wanted to be extra safe you could follow an alternative approach of limiting access at the field level for all the fields in the relevant templates. Depending on the number of fields that could be a hassle via the admin interface so you could look into doing it via the API.
  15. I have added support for this in v0.1.19. The scenario of editing user pages is a different kettle of fish than "normal" pages because you are then outside the structure of what are normally considered editable pages. So there isn't much that's useful in the dropdowns apart from the last dropdown.
  16. A recent GitHub request got me thinking about ways to get an overview of which fields are using which Textformatter modules. Here are a couple of approaches... 1. For all Textformatter modules that are in use, show the fields they are applied to Execute the following code in the Tracy Debugger console: // Loop over fields and get their Textformatters $textformatters = array(); foreach($fields as $field) { if(empty($field->textformatters)) continue; foreach($field->textformatters as $textformatter) { $textformatters[$textformatter][] = $field->name; } } d($textformatters); Any Textformatter modules that are not included in the dump output are not applied to any fields. 2. In the config screen for a Textformatter module, show the fields where the module is applied Add the following to /site/ready.php $wire->addHookBefore('ProcessModule::executeEdit', function(HookEvent $event) { // Get the module name $module_name = $this->wire('input')->get->name('name'); // Return if it's not a Textformatter module if(strpos($module_name, 'Textformatter') !== 0) return; // Add field to module edit form $event->wire()->addHookBefore('InputfieldForm(id=ModuleEditForm)::render', function(HookEvent $event) use ($module_name) { $value = ''; // Find any fields using this Textformatter and build markup value foreach($this->wire('fields') as $field) { if(empty($field->textformatters)) continue; foreach($field->textformatters as $textformatter) { if($textformatter === $module_name) { $value .= "<a href='{$this->wire('config')->urls->admin}setup/field/edit?id={$field->id}#fieldtypeConfig' target='_blank'>$field->name</a><br>"; } } } if(!$value) $value = 'No fields are using this Textformatter module'; // Add markup field to form $form = $event->object; $f = $this->wire('modules')->InputfieldMarkup; $f->label = 'Fields using this Textformatter module'; $f->value = $value; $form->insertAfter($f, $form->children->get('id=ModuleInfo')); }); });
  17. The padding around quoted text is a bit much, as can be seen in the quote immediately above. Seems to be coming from Uikit styles, which I guess are being included in their entirety just for the header. Could we strip it back a bit so only the needed styles are included? Or iframe the header part to avoid the styling conflicts? Another issue I've noticed since the upgrade: in iOS Safari (older versions) links are triggered on release of long touch (to open the context menu). This makes it difficult to open links in a new tab - you have to slide your finger away from the link before you release in order to select an item in the context menu, or else you navigate away within the current tab. This only applies to Safari and only on older Safari/iOS versions so perhaps it doesn't affect too many people. It's a pretty big annoyance to me though because you cannot select an alternative default browser on iOS (thanks Apple) and I don't want to have to buy a new iPad.
  18. The easiest way to implement this would be via a Repeater field containing a Text Unique field. But it feels a little wrong to me to use a Repeater for just a single repeating field (that might just be me) and the UI would be a bit more bulky than necessary. So personally I would be inclined to use a more streamlined repeating fieldtype such as Multiplier or Table. Then in a Pages::saveReady hook you do a $pages->count($selector) to check if any stores are using any of the submitted phone numbers and if so you reset the value for that number and show an inputfield error. If you need any tips for coding that just ask when you get to it. P.S. It seems like you could use Multiplier with Text Unique specified as the field type to multiply, but I tested it and the uniqueness is not enforced when these modules are combined.
  19. No problem here finding matches for a Page Reference field containing pages whose title starts with numbers. If the search value only contains numbers then the value will be interpreted as a page ID. In any case it's good to be specific about what you are wanting to match against to avoid any confusion. So if you want to match against the title use tags.title as $filter in your example.
  20. For me Tracy is showing a page load time of 163ms for the Home page on the front-end with the core blank profile. It would of course depend on how much you have going on in your site (template, modules, ready.php, etc) but your load time does sound slow. I'm running 5.7.19. I believe it's a matter of making sure your Apache and MySQL versions are compatible. Here are mine in case it helps:
  21. I don't know much about encryption, but if the email address is the entirety of the field value (i.e. there is a dedicated field that holds the email address and nothing but the email address) then couldn't you encrypt the search value and then match that encrypted value in the DB to find subscribers who have that exact email address? Of course this wouldn't be a solution if you wanted to match a part value (e.g. all subscribers with somedomain.com in their email address) but it would be something at least.
  22. Thanks for the info. From the discussion you linked to it sounds like the LIVE/LAZY features are still a work-in-progress and subject to change. So will wait a while before I delve into it. The thing that was confusing me was that the previous barDumpLive() didn't take any $options argument for maxDepth or maxLength which made me think there is no limit for these when a live dump is used. But no problem to keep using bdb() for larger dumps.
  23. Hi Adrian, Now that "live" is used as the default dump method there's an item in the shortcut methods description that should be deleted: And maybe in the docs too? https://adrianbj.github.io/TracyDebugger/#/debug-methods?id=bardumplive Or maybe move the explanation of live dumping to the intro of this section. Also, I'm trying to get my head around how this live dump works. Are you able to point me to a page in the Nette docs that covers this feature? I've been looking but haven't been able to find it. And if the dump data is loaded in realtime as the levels are expanded then how come there is truncation in the example shown below? Thanks.
  24. I think the DkCore module would need to create the parent page manually in the install() method (assuming DkCore is not a Process module). Then the other modules would specify the parent page by path as the "parent" within "page" within getModuleInfo(). But have you considered combining these three Process modules into a single Process module with several executeSomething() methods? Then you would create just a single page that uses this process and create a flyout menu for the other "execute" URL segments via the executeNavJSON() method. If you look at how some of the core Process modules that use flyout menus do this you'll get the gist of it.
  25. Me too, it's an essential module. I hesitate to say "should be in the core" because I know the PW philosophy on such things. But I wonder if certain modules that are widely needed and used could be highlighted somewhere within the core. So for instance there could be a link to PageRenameOptions from the PagePathHistory module config, so that when you install that module you get a heads-up that there is a useful related third-party module that you might want to consider also.
×
×
  • Create New...