Leaderboard
Popular Content
Showing content with the highest reputation on 08/11/2022 in all areas
-
@AAD Web Team, if you're wondering why status!=hidden doesn't work in this selector it's because status keywords like that are only supported in PageFinder selectors like $pages->find() that query the database, and not by selectors that match against a PageArray in memory. And although the docs don't make this clear $page->parents() actually adds all the parents one by one into a PageArray and then filters that PageArray by the selector. See here. It is a bit confusing that $page->children($selector) goes through PageFinder but $page->parents($selector) doesn't.4 points
-
A page’s status is a bit field technically you need to check whether it contains the hidden status. You can do this with ProcessWire selectors using the bitwise AND operator and negating the result: $page->parents('id!=1, !status&1024') Instead of the number 1024 you can also use the named constant: $page->parents('id!=1, !status&' . Page::statusHidden)4 points
-
Hi @HMCB Currently it is not so easy to provide an default value option for number fieldtypes other than Integer, because all core number Inputfieldtypes using the same rendering function: InputfieldInteger::render(), converting any init or default value to int. So currently there is no option to define default values with decimal places. The core InputfieldFloat and / or InputfieldInteger needs an update to allow default values with decimals. In a second step number fieldtypes could include an option to define a default value. I wrote a Module as a workaround until the core issues are fixed. https://github.com/kixe/FieldtypeDecimalPlusDefault3 points
-
Thx to another request by @wbmnfktr and issues that I had on my own project I've improved asset handling, autoloading and debugging in v1.13.8 It also adds a new method to prepend() scripts and styles (like uikit.theme.less in the example below). Adding something like addAfter('mystyle.css', 'theme.css') is on my list... A default <head> can now look like this (note all the html comments that should be quite helpful): <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- RockFrontend SEO by baumrock.com --> <title>Home</title> <meta property="og:title" content="Home"> <meta name="description" content="Home"> <meta property="og:description" content="Home"> <meta property="og:image" content=""> <meta property="og:image:type" content=""> <meta property="og:image:width" content=""> <meta property="og:image:height" content=""> <meta property="og:image:alt" content="Home"> <script>let rf_livereload_secret = 'rDksCMGEMFs87mNq3WrTaVug1tfeldQ0r9L4kUkfqghS'</script> <!-- DEBUG enabled! You can disable it either via $config or use $rf->styles()->setOptions(['debug'=>false]) --> <!-- autoloading of default scripts/styles enabled - disable using ->setOptions(['autoload'=>false]) --> <!--rockfrontend-styles-head--> <!-- loading /var/www/html/site/templates/uikit-3.15.2/src/less/uikit.theme.less --> <!-- loading /var/www/html/site/templates/layouts/_global.less --> <!-- loading /var/www/html/site/templates/sections/footer.less --> <!-- loading /var/www/html/site/templates/sections/hero.less --> <!-- loading /var/www/html/site/templates/sections/job-footer.less --> <!-- loading /var/www/html/site/templates/sections/menu.less --> <!-- loading /var/www/html/site/templates/sections/rocket.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/FactsBar.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/IconBox.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/IconRow.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/PagesGrid.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/QuoteSlider.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/Spacer.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/Team.less --> <link rel='stylesheet' href='/site/templates/bundle/head.css?m=1660204105'> <link href='/site/modules/RockFrontend/Alfred.css?m=1660124218' rel='stylesheet'> <link href='https://use.typekit.net/zeg8qpc.css' rel='stylesheet'> <link href='/site/templates/sections/foo.css?m=1660207177' rel='stylesheet'> <!--rockfrontend-scripts-head--> <script src='/site/modules/RockFrontend/Alfred.js?m=1660123300'></script> <script src='/site/modules/RockFrontend/livereload.js?m=1660123300'></script> <script src='/site/templates/uikit-3.15.2/dist/js/uikit.min.js?m=1659941286' defer></script> <script src='/site/templates/uikit-3.15.2/dist/js/uikit-icons.min.js?m=1659941286' defer></script> <script src='/site/modules/RockFrontend/lib/alpine.min.js?m=1660123300' defer></script> <script src='/site/modules/RockFrontend/RockFrontend.js?m=1660203134' defer></script> </head> ? v1.13.10 makes sure that LESS is forced to recompile on modules::refresh3 points
-
Theres so much going on in this one, great work... hard to keep up track ?2 points
-
First of all, listen to Bernhard, but to answer your question, you can get pages by position using the selector "start": https://processwire.com/docs/selectors/#limit The number is the zero-based index of the first element you want. The order will reflect that of the page tree unless you specify the "sort" selector. I haven’t thouroughly checked it out, but you may be interested in the Virtual Parents module: https://github.com/Toutouwai/VirtualParents2 points
-
Thanks @bernhard and @Jan Romero. I didn't think of how status works as a bit field, and I've never used the bitwise 'or' operator in a selector. The code snippet with Page::statusHidden is very useful, thank you. The part of the documentation I found confusing was in the selectors documentation where it says, "Pages with hidden or unpublished status will not appear in the results from database-querying selectors that can return multiple pages (i.e. functions that return the PageArray type). For instance $pages->find(), $page->children(), etc." However, I understand it now. Thanks @Robin S for explaining the underlying logic to why $page->children() and $page->parents() work differently with hidden pages. I can see from your linked post how this has been discussed previously. Unfortunately, in my forum searching before asking this question I didn't come across your post – so thanks for pointing me to it.2 points
-
I don't see that the docs say anything different: https://processwire.com/api/ref/page/parents/ You can use parents("status=1"), but that might also exclude other pages (like pages having errors after save). Or you do a foreach and check $page->isHidden() for every item.2 points
-
Looking at your code, and specifically your ___uninstall() method, I can spot at least a few potential issues. $custom_order_pages = wire('pages')->find('template=template_custom_orders|template_custom_order')->count(); // if ($custom_order_pages > 0) // throw new WireException("There are pages using custom-order-templates. Remove those first before uninstall"); foreach($custom_order_pages as $custom_order_page){ $custom_order_page->delete(); } The foreach loop above doesn't make any sense. You're essentially trying to iterate over the count() value, which is an integer. If you remove the "->count()" part, it's more likely to work — unless your pages are hidden/unpublished, in which case you should also add "include=all" to the selector string. if($fields->get('custom_order_id')) : foreach ($fields->get('custom_order_id')->getFieldgroups() as $fieldgroup) { $fieldgroups->delete($fieldgroup); } endif; if($fields->get('custom_order_products')) : foreach ($fields->get('custom_order_products')->getFieldgroups() as $fieldgroup) { $fieldgroups->delete($fieldgroup); } endif; if($fields->get('custom_order_customer_name')) : foreach ($fields->get('custom_order_customer_name')->getFieldgroups() as $fieldgroup) { $fieldgroups->delete($fieldgroup); } endif; if($fields->get('custom_order_customer_address')) : foreach ($fields->get('custom_order_customer_address')->getFieldgroups() as $fieldgroup) { $fieldgroups->delete($fieldgroup); } endif; if($fields->get('custom_order_customer_emailaddress')) : foreach ($fields->get('custom_order_customer_emailaddress')->getFieldgroups() as $fieldgroup) { $fieldgroups->delete($fieldgroup); } endif; The part above looks fine, but keep in mind that none of these fields were added to the "fieldgroup_custom_orders" fieldgroup, so that won't get removed. You should probably add something like this right after the lines above: $fieldgroups->delete($fieldgroups->get('fieldgroup_custom_orders')); Also this is likely unrelated to your bigger issue(s) here, but note that this part doesn't seem quite right: $template_custom_orders->childrenTemplates = array($template_custom_order->id); There's no "childrenTemplates" property on Templates. What you probably meant was childTemplates. Finally, your ___install() method is rather error prone. In case any of the fields already exist, you will run into problems. For an example, look at these lines here: if(!$fields->get('custom_order_id')) : $custom_order_id = new Field(); // int or text $custom_order_id->type = $this->modules->get("FieldtypeInteger"); $custom_order_id->title = 'Custom Order ID'; $custom_order_id->name = wire('sanitizer')->pageName($custom_order_id->title, true); $custom_order_id->label = 'Order ID'; $custom_order_id->tags = 'kiosk'; $custom_order_id->save(); endif; What happens here is that a) if custom_order_id field is not found, it will be created and stored in $custom_order_id, but b) if it doesn't exist, then it won't be created and it also won't be stored in $custom_order_id. Basically if install/uninstall has been only partially completed, even once, then you're likely going to run into issues. Here's one approach that should work a bit more reliably: $custom_order_id = $fields->get('custom_order_id'); if(!$custom_order_id) : $custom_order_id = new Field(); // int or text $custom_order_id->type = $this->modules->get("FieldtypeInteger"); $custom_order_id->title = 'Custom Order ID'; $custom_order_id->name = wire('sanitizer')->pageName($custom_order_id->title, true); $custom_order_id->label = 'Order ID'; $custom_order_id->tags = 'kiosk'; $custom_order_id->save(); endif; It's quite likely that this error is linked to the issue I mentioned above about your install/uninstall method being error prone: if the process has failed even once, this part will not work as expected: if(!$fieldgroups->get('fieldgroup_custom_orders')) : $fieldgroup_custom_orders = new Fieldgroup(); $fieldgroup_custom_orders->name = 'fieldgroup_custom_orders'; $fieldgroup_custom_orders->add($this->fields->get('title')); $fieldgroup_custom_orders->save(); $this->message('creating fieldgroup fieldgroup_custom_orders'); endif; This — and every other code snippet that uses similar approach — should be replaced with something like this instead: $fieldgroup_custom_orders = $fieldgroups->get('fieldgroup_custom_orders'); if(!$fieldgroup_custom_orders) : $fieldgroup_custom_orders = new Fieldgroup(); $fieldgroup_custom_orders->name = 'fieldgroup_custom_orders'; $fieldgroup_custom_orders->add($this->fields->get('title')); $fieldgroup_custom_orders->save(); $this->message('creating fieldgroup fieldgroup_custom_orders'); endif; If your module needs to create templates via the API and add fields to said templates, you do need fieldgroups. There's no way around that.2 points
-
Modules Directory: https://processwire.com/modules/rock-frontend Github: https://github.com/baumrock/RockFrontend1 point
-
Docs & Download: rockettpw/seo/markup-sitemap Modules Directory: MarkupSitemap Composer: rockett/sitemap ⚠️ NEW MAINTAINER NEEDED: Sitemap is in need of developer to take over the project. There are a few minor issues with it, but for the most part, most scenarios, it works, and it works well. However, I'm unable to commit to further development, and would appreciate it if someone could take it over. If you're interested, please send me a private message and we can take it from there. MarkupSitemap is essentially an upgrade to MarkupSitemapXML by Pete. It adds multi-language support using the built-in LanguageSupportPageNames. Where multi-language pages are available, they are added to the sitemap by means of an alternate link in that page's <url>. Support for listing images in the sitemap on a page-by-page basis and using a sitemap stylesheet are also added. Example when using the built-in multi-language profile: <url> <loc>http://domain.local/about/</loc> <lastmod>2017-08-27T16:16:32+02:00</lastmod> <xhtml:link rel="alternate" hreflang="en" href="http://domain.local/en/about/"/> <xhtml:link rel="alternate" hreflang="de" href="http://domain.local/de/uber/"/> <xhtml:link rel="alternate" hreflang="fi" href="http://domain.local/fi/tietoja/"/> </url> It also uses a locally maintained fork of a sitemap package by Matthew Davies that assists in automating the process. The doesn't use the same sitemap_ignore field available in MarkupSitemapXML. Rather, it renders sitemap options fields in a Page's Settings tab. One of the fields is for excluding a Page from the sitemap, and another is for excluding its children. You can assign which templates get these config fields in the module's configuration (much like you would with MarkupSEO). Note that the two exclusion options are mutually exclusive at this point as there may be cases where you don't want to show a parent page, but only its children. Whilst unorthodox, I'm leaving the flexibility there. (The home page cannot be excluded from the sitemap, so the applicable exclusion fields won't be available there.) As of December 2017, you can also exclude templates from sitemap access altogether, whilst retaining their settings if previously configured. Sitemap also allows you to include images for each page at the template level, and you can disable image output at the page level. The module allows you to set the priority on a per-page basis (it's optional and will not be included if not set). Lastly, a stylesheet option has also been added. You can use the default one (enabled by default), or set your own. Note that if the module is uninstalled, any saved data on a per-page basis is removed. The same thing happens for a specific page when it is deleted after having been trashed.1 point
-
...or see the docs https://processwire.com/docs/fields/dependencies/1 point
-
1 point
-
1 point
-
There's nothing to stop you having a (perhaps hidden) field 'index' on each month page representing the month's number, then your selector above would work (or very nearly work). If I was doing something like you are, I would probably have some code in _init.php or _ready.php or even at the top of a page template to programmatically create new 'year' and 'month' pages well in advance, creating and populating that 'index' field as well and probably leave them unpublished so that they can be quickly and easily published when required. I think that would work. Probably.1 point
-
You mean MarkupAdminDataTable? https://processwire.com/api/ref/markup-admin-data-table/ Have you tried setting encodeEntities to false? You’ll have to escape the contents yourself, but you’ll be able to use HTML tags.1 point
-
Well, yes and no ? I love (!) Bernhards work but I just stick to my solution for now. If you take a closer look at the page structure in the backend here, I think no one can't deny that this is easier to maintain than having all event pages underneath a single parent. I am thinking about the client who has to do the content work at the end... From a technical perspective this is also convenient, because you can view all events of a specific month directly via URL, like www.mysite.com/programm/2022/august/ Otherwise I would have to make use of URL segments to make the filtering happen.1 point
-
Counter-question: Are you sure you want to have that setup on the backend? In my experience it is much easier to just save all events under one single parent (eg Events / EventItem) and just let every event have one date field. Then you can easily sort by this date field and do filters etc (like showing only future events). Also changing the date for example would be much easier than changing the date of the event and then additionally having to move the page in the page tree to not get false results (eg an event from august showing up in july)...1 point
-
If I'll really need PageReference, I think I can use hook + JS which was mentioned in the topic above. However, I found that using PageReference for my needs is superfluous, I can simply use ->find() method instead.1 point
-
As soon as you want to add fields to templates you need to work with fieldgroups, as fieldgroups are the thing that connect templates with fields. I think the fact that many modules don't use fieldgroups is that - as you have realised - it is not that easy to create fields/templates/fieldgroups via API as there is a lot of things you need to take care of and that are not obvious and make things tedious. That's only one example of what I said above. But there are modules that create fieldgroups, of course. For example here: https://github.com/kongondo/Blog/blob/master/BlogInstallWizard.php The frustration you are going through is exactly the reason why I built RockMigrations...1 point
-
Hi @Robin S Honestly, I am not really sure there is a need for a time limit at all. Given that only a superuser can start a session, I am not really sure we need a limit different from whatever the PW session timeout is in config.php Let me take a look - I think I can probably remove the time limit and just ensure that the session is killed when the panel is closed or if you click the End Session button.1 point
-
Not sure exactly what you are wanting to achieve but, if it helps, here is some code I used to hook User::hasPagePermission. Obviously the context is specific to my app (a membership system), but maybe there are some useful ideas. /** * PAGE PERMISSIONS * Allow member users to edit etc. pages relevant to them (access via AIM in My NCOG) **/ wire()->addHookAfter('User::hasPagePermission', function(HookEvent $event) { // Get the object the event occurred on, if needed $user = $event->object; // An 'after' hook can retrieve and/or modify the return value $return = $event->return; // Get values of arguments sent to hook (if needed) $permission = $event->arguments(0); $p = $event->arguments(1); /* Your code here, perhaps modifying the return value */ // Is it a page we need to customise access for? $templates = ['Membership', 'Member', 'Profile', 'Subscription', 'Payment', 'MemberShop', 'Booking', 'NewsItem']; $permissions = ['page-edit', 'page-add']; $currentUser = $this->users->getCurrentUser(); if ($p and in_array($p->template, $templates) and $permission and in_array($permission, $permissions)) { if ($currentUser and $currentUser->isLoggedin()) { $this->log->save('debug', 'In hasPagePermission hook for Page = ' . $p . ', Permission = ' . $permission . '. Current user is ' . $currentUser); if ($currentUser->hasRole('member')) { $email = $currentUser->email; $memberPage = ($email and $email != '') ? $this->pages->get("has_parent=/memberships/, template=Member, email=$email") : null; if ($currentUser->memberOnly != 0) { $return = false; $this->log->save('debug', 'Member only'); } // Member-only users can only access pages as defined below // Admin members will also have their normal permissions if ($memberPage and $memberPage->id) { $membershipPage = $memberPage->parent; $this->log->save('debug', 'Membership page = ' . $membershipPage->id); $profilePage = $membershipPage->id ? $membershipPage->get("template=Profile, include=hidden") : null; $siblings = $memberPage->siblings("template=Member, include=hidden"); // includes member page itself $shops = $membershipPage->id ? $membershipPage->find("template=MemberShop, include=all") : null; $currentSub = $membershipPage->id ? $membershipPage->latestSubscription() : null; $subsPaymentPages = $membershipPage->id ? $membershipPage->find("template=Payment, parent=[template=Subscription], include=hidden") : null; $draftNewsPages = $membershipPage->id ? $memberPage->find("template=NewsItem, include=all") : null; $bookingPages = $membershipPage->id ? $membershipPage->find("template=Booking, include=hidden") : null; $editablePages = new PageArray(); $addablePages = new PageArray(); $editablePages = $editablePages->add($membershipPage)->add($profilePage)->add($siblings)->add($currentSub)->add($shops)->add($subsPaymentPages)->add($draftNewsPages)->add($bookingPages); $addablePages = $addablePages->add($membershipPage)->add($memberPage); // pages where creation of children is allowed $this->log->save('debug', 'Editable pages = ' . $editablePages->implode(', ', 'id')); $this->log->save('debug', 'Addable pages = ' . $addablePages->implode(', ', 'id')); if ($editablePages->has($p) and $permission == 'page-edit') $return = true; if ($addablePages->has($p) and $permission == 'page-add') $return = true; } } $retStr = $return ? 'true' : 'false'; $this->log->save('debug', 'Returning ' . $retStr); } } // Populate back return value, if you have modified it $event->return = $return; });1 point
-
@Clarity, could you please share, what was the solution?1 point
-
@taotoo thanks for this - and i actually can't recall how that got fixed but i did sync the repo and the fix was probably in there.. I will definitely get around to do a deep dive check and make sure it works and add the AdminThemeCanvas to the code as you have indicated; I didn't even know about that new theme...1 point