Jump to content

SwimToWin

Members
  • Posts

    89
  • Joined

  • Last visited

Everything posted by SwimToWin

  1. Hi @Markus Thomas - Thank you very much for pointing out the opportunity to use url hooks. I can make it work on one page, but it keeps failing on the product page and I cannot tell why; I'm using PW v3.0.200. Anyways - using urlSegments() works: #workaround #uglyButWorks #inspiration Code // Match url - example: https://www.example.com/myproduct/r/foo1234 if( in_array($page->template, ['product','redirect']) && $input->urlSegment1()=='r' && $input->urlSegment2() ) { $p = $pages->findOne("template=redirect, title=" . $input->urlSegment2() ); if( $p->link ) { // Page exists according to "page that uses a redirect template" -> redirect to specified destination page. // Support absolute and relative links $p->link = str_replace(['https://www.example.com/','http://www.example.com/','//www.example.com/','www.example.com'], '', $p->link); $p->link = ltrim($p->link,'/'); $url = "//{$config->httpHost}/$p->link"; } else { // Fallback: Page doesn't exist, so redirect to product page $url = "//{$config->httpHost}/{$page->url}"; } printf("<p>Redirecting to <a href='%s'>%s</a></p>", $url, $url); $session->redirect($url); } Setup Redirect template with Title and Link text fields.
  2. Good idea, @Markus Thomas. Unfortunately these url hooks don't work in my use case because the redirect happens "below existing pages", as explained here: $wire->addHook('/existing-page/r', function($event) { return "Hello R"; // Not shown (contents from the "nearest parent page" is shown) }); $wire->addHook('/non-existing page/r', function($event) { return "Hello"; // Works });
  3. Hi, I want to redirect users that hit 1) pages using a specified template 2) when the url is using a specific syntax. Url syntax is: /PRODUCT/redir/PAGEID Example: /foo/redir/1234 My intention is to redirect the user to the specified PAGEID - but I don't know how to user $input in a hook. How might that be done with hooks in ready.php? $this->addHookBefore('Session::redirect', function(HookEvent $event) { $session = $event->object; // (Product template always lives a root level) if( TEMPLATE == 'product' && INPUT->urlSegment1()=='r' ) { $dest = $pages->get(PAGEID); $session->redirect( $dest->url ); } });
  4. When working with Checkboxes ("Type: Page Reference - Input field type: Checkboxes - with Page field value type: Multiple pages PageArray" fields, that is), this works: $rs = $pages->find('template=foo, parent=/bar/'); foreach ($rs as $p) { $p->of(false); $p->myCheckboxes = null; // Unset all values first $p->myCheckboxes = 'baz'; // Then set the active checkbox with name (or, use Page ID) $p->save(); }
  5. Small request: When working with files outside ProcessWire, it would be useful to know the the public / web folder. Having this folder or directory will allow me to work with the "non-Processwire file system". Example: /var/sites/www.example.com/public/ <- (or whatever your hosting provider calls the public directory for a website) I can get the directory with $_SERVER['DOCUMENT_ROOT'] - unfortunately, the $_SERVER variable is easily manipulated and therefore unsafe (needs to be escaped and such). sprintf('%s/%s/', $_SERVER['DOCUMENT_ROOT'], 'whatever'); Currently print_r($config->paths) outputs two array keys that hold (too deep) info about the public web directory: [sessions] => /var/sites/www.example.com/public/site/assets/sessions/ [classes] => /var/sites/www.example.com/public/site/classes/
  6. I'm importing data from an external system into ProcessWire. Each of the imported records have a unique ID. How might I use the unique ID to prevent duplicate records in ProcessWire? What I want: When importing data find the foreign record ID use it to check for duplicates if a duplicate record is detected, skip it import data into ProcessWire by creating a page in /import/ continue to next record ProcessWire: Later I'll move each page to another location ... meaning that '/import/' will be empty the next time, I run an import job Looking into possible solutions: Unfortunately, ProcessWire Unique Text Fieldtype doesn't do the trick. (ProcessWire Unique Text Fieldtype will allow the page to be created - only the field with a duplicated field value will be blank. In my case, the duplicate record needs to be blocked / *not* created.) Could it be solved by modifying the code for ProcessWire Unique Text Fieldtype?
  7. Solution: has('name') does the job, that's also self-explanatory .. compared to using IDs, as I did in my tests above. var_dump( $page->config->has('foo') ); // bool(true)
  8. Thanks Andreas @AndZyk - both for solution and find() explanation; never used find() much
  9. It's incredible what you can do with ProcessWire. I did hit a limitation on my side though... ? and would like to ask for some support: Problem: I'm using a Page Reference Checkboxes field that gets it's Options from a few Pages; Page field value type is set to "Multiple pages PageArray". Screenshot: What I want: to check if each checkbox is checked or not (without using a foreach loop). What I tried: var_dump( $page->config->has(1898)); var_dump( $page->config->getValues()); // (WireArray is output, I don't know how to use that.) var_dump( $page->config->getValues(1898)->id ); // Warning: Attempt to read property "id" on array var_dump( $page->config->get(1898) ); // NULL var_dump( $page->config->get(1898)->id ); // Warning: Attempt to read property "id" on null var_dump( $page->config->first()->id ); // int(1898) ... better, but how to get the next value? var_dump( $page->config[1898] ); // bool(false) var_dump( $page->config->find(1898) ); var_dump( $page->config->find(1898)->id ); var_dump( $page->config(1898) ); NULL (checkbox is set) var_dump( $page->config->1898 ); // unexpected integer "1898", expecting identifier or variable or "{" or "$" var_dump( $page->config->find(1898)->id ); // Fatal Error: Uncaught Error: Call to a member function find() on null var_dump( $page->config->has(1898)); // Fatal Error: Uncaught Error: Call to a member function has() on null $a = $page->config->getValues(); echo isset($a->1898->id) ? 1 : 0; $a = $page->config->getValues(); echo isset($a->1898->id) ? 1 : 0; // Parse Error: syntax error, unexpected integer "1898", expecting identifier or variable or "{" or "$" echo isset($a[1898]->id) ? 1 : 0; // 0 (but checkbox is set?) echo isset($a[1898]['id']) ? 1 : 0; // 0 (but checkbox is set?) var_dump( $page->config->eq('foo')->id ); // int(1898) var_dump( $page->config->eq('foo') ); // wirearray var_dump( $page->config->has('foo')); // bool(true) // Is this a bug? eq() returns same Page ID for two names. echo $page->config->eq('foo'); // 1898 (correct) echo $page->config->eq('bar'); // 1898 (incorrect, the ID is 1899. ... and thanks for always being a helpful, constructive, and knowledgeable community! Make a great day! ?
  10. When I use the suggested solution, then I loose the default markup from main.php. How might I keep the default markup from main.php
  11. `<?php var_dump($page->content3); ?>` outputs NULL. It seems $page->content3 isn't populated?
  12. I use these Markup Regions and Bulma CSS Framework in _main.php: <section class="section"> <div class="container"> <div id="content1" class="content"></div> </div> </section> <section class="section"> <div class="container is-fluid"> <div id="content2"></div> </div> </section> <section class="section"> <div class="container"> <div id="content3" class="content"></div> </div> </section> I want to specify HTML tags required by a CSS framework - and it shall be output only when the Markup Region produces an output. I want the full SECTION to be hidden in case the region doesn't output - because if the SECTION tags are output then it will affect the layout in unintended ways. So my question is, how can I hide SECTION tags when the region doesn't produce an output? To me, the challenge here is that Bulma requires a layout structure before Content 1-3 are output (specifically, the SECTION and DIV.container tags) - and it seems this pattern is always output by Markup Regions - which is causing the mentioned issues. Feel free to suggest alternative ways to work with Markup Regions and Bulma (or other CSS frameworks).
  13. Regarding multi-language fields such as TextLanguage, TextareaLanguage, and PageTitleLanguage: When multi-language fields are shown in Page Edit mode, I often use them next to non-multi-language fields. That makes the page appear a bit disorganized and cluttered because multi-language fields vs non-multi-language fields don't align horizontally. The reason is that multi-language field have "language switcher tabs" that forces the field to "jump down" whereas normal fields stay in the normal position. See screenshot 1. It makes me sea sick! ? Suggested solution is to move the "language switcher tabs" up so that it aligns with the field label. See screenshot 2.
  14. @dragan - That'll work. Thanks! I use the snippet below that copies the full Image object so that all Image properties remain intact for use in the subsequent foreach(): foreach ($page->children() as $p) { $imgs = $pages->get($p->foo->id)->images; if( isset($p->foo->id) && $imgs ) { $gmi = []; foreach ($imgs as $img) { $gmi[] = $img; } foreach ( array_reverse($gmi) as $v) { echo "<img src=\"{$v->width(140)->url}\" alt=\"{$p->foo->title}\">"; } } }
  15. How might I programmatically output images from an Image field from another template in descending order? I want to reverse the order of images on the front-end page (see code below). I want to keep the order in ProcessWire Admin. The Image field accepts multiple images. Code: foreach ($page->children() as $p) { if( isset($p->foo->id) && $pages->get($p->foo->id)->images->count>0 ) { foreach ($pages->get($p->foo->id)->images as $img) { echo "<img data-src=\"{$img->width(140)->url}\" width=\"\" height=\"\" alt=\"{$p->foo->title}\" class=\"uk-align-right uk-visible@m\" uk-img>"; } } } Things I tried (that didn't have an effect): $pages->get($p->foo->id)->images->sort("sort=-sort") $pages->get("id={$p->foo->id},sort=-sort")->images I also wanted to try a for() loop but didn't know how to.. # Failed attempts: $pages->get($p->foo->id)->images[0]; $pages->get($p->foo->id)->images->1; # This works - but only for first and last (not a third image) and I would need to check if each image existed. $pages->get($p->foo->id)->images->first; $pages->get($p->foo->id)->images->last; I am aware that ProcessWire isn't specifically designed for working with child pages this way - it's probably even a bad practice - it's just that it almost always works very, very well. ? PS: Would you normally set the width and height attributes, or leave them out?
  16. @adrian's script works like a charm when executed from a template page - I followed these steps: Step 1 - Create new template with same fields set as on the repeater field. * Field names must match (if they don't, you might map them manually). Step 2 - Add the script to a Template. * I set repeater field name and page template name. * The script will attempt to copy all "repeater pages" found by '$page->$rf'. So, I used a template file that could access the repeater fields with '$page->$rf'. Step 3 - Run the migration by visiting the page. * At this point, I removed the script and inspected the results. Results: * All fields were migrated (saved me a ton of detailed copy-paste work!). * Title field was set to a code ("1234-9234") because my Repeater didn't have a Title field - but it was easy to update manually. * Url name field was set to a code ("1234-9234") - and updated after I manually pressed Save on each page. * Even language fields were correctly migrated. Nice! <?php $rf = "my_source_repeater_fieldname"; //repeater field name $pt = "my-destination-page-template"; //page template name foreach($page->$rf as $r){ $np = new Page(); $np->of(false); $np->template = $pt; $np->parent = $page; foreach($r->fields as $f){ $np->$f = $r->$f; } $np->save(); }
  17. Where I am: Edit Page -> Settings -> Parent -> "+Change". Edit Field -> Page Reference field -> Input tab -> "Selectable pages (Select the parent of the pages that are selectable)" -> "+Change". ... and possibly other locations where the Page Tree is used. Quality of life improvement: When modifying Parent Pages (Edit Page) or Selectable pages (on a Page Reference field) and I press "+Change" to change the Parent Page, it would be nice if the current Parent Page came into focus without effort. Current solution: As an editor, I am required to find the Parent Page / "Page Reference parent page" manually which makes me think ("where did I put that page?"), takes a bit of time ("click, click, click"), and is hard on a larger site with a deep structure. The unmet goals are: I instantly see the context for the current Parent Page. I can effortlessly select another Parent Page. Constraints: Large website makes it hard to navigate and get a view of the Page Tree. I don't want to pick an incorrect Parent Page. It's sometimes difficult to see if I choose the right parent. The Parent Page must be in the current "Page Branch" ("/foo/bar/baz/" -> "/foo/quz/baz/"). I don't always need to see/browse the full Page Tree. Sometimes a lot of parent pages are unnessarily shown (larger websites with 4-5 levels of pages). Better: When I open the Edit Page / Edit Field page and click "+Change", I want the tree structure to expand (in a modal?) and bring the current Parent Page into focus. It's one of those small things that help create a smooth user experience. Additional thoughts: The displayed Page Tree only shows the current Page Branch; this might optionally be specified on the Template. Hide "unneeded" parent pages in a larger websites with 4-5 levels of pages (how?). Perhaps you have additional ideas that might improve working with Parent Pages when editing a page or a field?
  18. 1) It seems, the SEO reason that I gave is being taken very literaly. To me, it's more a matter of having built-in flexibility to structure pages without necessarily exposing the structure. I may not want to expose the parent page in the front-end. 2) "Virtual Pages" aligns with Ryan's "no assumptions" design principle. ProcessWire allows the admin to structure pages - but doesn't make (too many) assumptions about how these pages are output in the frontend. Or, to put it in the words of Ryan, "ProcessWire doesn't control the front-end, there are very few assumptions that can be made from an editing perspective." See also: No assumptions (cute interview!). 3) Short urls are cool - SEO or not - and "Virtual Pages" help me achieve that. Consider these versions of the same url: Long: www.example.com/book-reviews/wheres-wally-in-hollywood/ Short: www.example.com/wheres-wally-in-hollywood/ 4) WordPress has a bunch of change / shortify your urls tools - some quick examples: https://wordpress.org/support/article/pages/#changing-the-url-of-your-pages https://wordpress.org/plugins/url-shortify/ @bernhard URL hooks are nice. Thanks for that pointer. @wbmnfktr Thanks for the VirtualParents module link. I'm trying not to use plug-ins and would prefer to have this flexibility built-in (or use hooks). Thanks for constructive inputs and perspective. I'll rest my case.
  19. BACKGROUND SEO matters and so hiding pages behind a "section" is not necessarily good - example: Current practice is to show the pages "Foo, Bar, Baz" in a section. https://www.example.com/resources/foo https://www.example.com/resources/bar https://www.example.com/resources/baz For SEO reasons, it's better to show the page at root level like so: https://www.example.com/foo https://www.example.com/bar https://www.example.com/baz PROBLEM: LACK OF ORGANIZATION WHEN ALL PAGES ARE PUBLISHED AT ROOT LEVEL This design is fully possible today. However, the root folder becomes disorganized when all pages are published in the root - and the pages tree structure is not of much use when all pages are published in the root. SOLUTION: VIRTUAL PAGES TO THE RESCUE As a publisher, when publishing many pages that have a root level url, I want to organize my pages below a Virtual Page (that doesn't have a url), so that pages are organized in a Pages Tree Structure (using "Virtual Pages"). What is a "Virtual Page"? Virtual Page can never have a name (Admin -> Page -> Settings -> Name). The Name field is simply blank The Name field is never used in the url for child pages. Virtual Page is a container used to organize other pages. Virtual Page is never shown in the front-end. Virtual Page is shown in the Editing interface only. Virtual Page might have a Template - but the template can only be used in the Admin interface. Virtual Page might have fields (Title, Summary, Text etc.) - but the contents cannot be shown online.
  20. Request to have a selector operator that allows me to filter out results that do not begin with a specified comparison value. For instance like so: `^!=` `$!=` (nice to have-addition) ... think of it as an extension of the `!=` operator. Consider these use cases: In the Admin Page Editor I want to show the field "Summary" only when the page path doesn't start with "/foo/" (preferably not using LIKE to do the comparison). Selectors don't allow checking the root parent for a path (as I recall, that used to be possible, I might be wrong though). Filtering out the field might be done with these Selector operators: path^!=/foo/ path^!=/foo/|/bar/|/baz/ Result: Page path: /foo/ and /foo/one/two/ "Summary" field is not shown. Page path: /bar/ and /bar/one/ "Summary" field is shown. See also the Selectors documentation https://processwire.com/docs/selectors/ https://cheatsheet.processwire.com/selectors/ `^=` - Starts with phrase/text Word or phrase appears at start of compared value. `$=` - Ends with phrase/text Word or phrase appears at end of compared value. `^!=` - Starts doesn't with phrase/text (if/when this request is implemented) Word or phrase doesn't appears at start of compared value. `$!=` - Ends doesn't with phrase/text (if/when this request is implemented) Word or phrase doesn't appears at end of compared value.
  21. @bernhard - Where does d() come from? In my ProcessWire 3.0.165 (production) I get: $str = "| Entry | | Foo |"; $md = $modules->get('TextformatterMarkdownExtra'); $md->format($str); d($str); // Fatal Error: Uncaught Error: Call to undefined function d() // Same for: d('foo');
  22. @bernhard - Please elaborate. In ProcessWire 3.0.165 I get this intermediate "Add New" page when creating a page. If only one template can be used, the page is still shown - just without the Template field. <- The purpose is to get rid of this "Add New" page.
  23. Suggested roadmap candidates to improve core: One-step Page Creation: Skip "Add New" and go directly to the resulting page. Better un-global Title fields. Page urls with auto-incrementing IDs (and without Page Name parts). Easier Permissions for Users, Roles, Templates & Pages
  24. I love nice urls - but I also recognize that they are not always needed nor desired due to the additional steps in page creation. Suggested solution: Page ID Page ID is a per-template auto-incrementing number. No. series might be added on a per-template basis (to be configured by webmaster). Page url Replace the full page url with an ID (as an optional configuration). Page url might then change to something like: www.example.com/page/1234 Editing (Page Tree is much less important in this scenario.) Like Drupal's Node IDs (nid). Why this change? Name may reveal confidential info. Name may not matter on certain templates. Page creation is no longer a two-step process; much like adding a row in MySQL. Benefit: This change will make it easier to use ProcessWire for other purposes than websites ("Oh - so ProcessWire is also a finance system!").
×
×
  • Create New...