All Activity

This stream auto-updates     

  1. Past hour
  2. @thetuningspoon, sounds like a bug then, as if the dependency evaluation does not account for the situation where a field may be excluded from ProcessProfile. Your code changes look like a improvement - maybe log an issue and suggested fix on GitHub?
  3. Hi all, I have just committed a major new version (2.0.0) on the dev branch ( This version has breaking changes if you use the frontend export/import API methods!! Changes include: changed API methods - please see ReadMe for details: module config settings to: set defaults for import and export parameters (delimiter, enclosure, etc) can users override the default parameters can users can select columns/order in exported CSV can users use an InputfieldSelector interface to filter table rows (this is an enhanced version of the built-in Table "Find" interface available when you have pagination enabled) I would like to make this the stable (master) version as soon as possible because the old API methods were not well constructed so I would really appreciate testing of this new version if you have any time. Thanks! PS - has anyone out there actually been using the API methods?
  4. @Robin S No, I am using ID. It works fine when editing the user in ProcessPageEdit (or from Access/Users), but not ProcessProfile.
  5. Today
  6. Sure, be my guest.
  7. Are you using the role name in the dependency selector string? If so you need to use the role ID instead.
  8. I just ran into this same issue. I tried to make a field dependent on one of the roles and it broke the profile, even though neither the roles field or the dependent field were visible in the profile at all. I created a copy of the ProcessProfile module under /site/modules/ and replaced this: if(count($form->getErrors())) { $this->error($this->_("Profile not saved")); return; } With this: $errors = $form->getErrors(); if(count($errors)) { if(count($errors) == 1 && strpos($errors[0], 'showIf') !== false) { // Everything is okay } else { $this->error(implode('; ', $errors)); // Show the actual errors instead of just a generic message return; } } This way if there is only one error message and it is related to a 'showIf' field dependency, the form will save anyway.
  9. Wow, this is exactly what I am looking for. Great thanks!
  10. Do you want something like this? Moving a page before Admin > Pages? Then try using $pages->insertBefore(), no need to change page status at all. $anchor = $pages(3); // `Pages` page $sortee = $pages(1354); // page to move before `Pages` $pages->insertBefore($sortee, $anchor); <?php /** * Sort one page before another (for pages using manual sort) * * Note that if given $sibling parent is different from `$page` parent, then the `$pages->save()` * method will also be called to perform that movement. * * @param Page $page Page to move/sort * @param Page $sibling Sibling that page will be moved/sorted before * @param bool $after Specify true to make $page move after $sibling instead of before (default=false) * @throws WireException When conditions don't allow page insertions * */ public function insertBefore(Page $page, Page $sibling, $after = false) { /* ... */ } EDIT: Moving before Tree works too $anchor = $pages(8); // `Tree` page $sortee = $pages(1354); // page to move before `Tree` $pages->insertBefore($sortee, $anchor);
  11. Currently the page tree(name=page) under admin is locked. I would like to generate a page to place above the page tree, using $page->sort = 0, but it is not possible before removing the statusSystemOverride attached to it. I tried to remove the status like this: $pages = $this->wire('pages'); $tree = $pages->get('name=page, template=admin'); $tree->removeStatus(Page::statusSystemOverride); $tree->save(); And recover the status after saving my generated page $p = new Page(); $p->template = 'admin'; $p->title = 'Some Page'; $p->name = 'somepage'; $p->parent = $pages->get(2); $p->process = 'SomeProcess'; $p->sort = 0; $p->save(); $tree->addStatus(Page::statusSystemOverride); $tree->save(); And the Page group is disappeared on the sidebar. I cannot recover it and need to reinstall the PW. I am developing a module so I would like to know the correct way to place page above the page tree by API not by drag and drop. Thanks.
  12. Thanks for the report @szabesz - I have now overwritten the PHP time limit for these actions, so that should take care of your timeout issues. Regarding the duplicate names problem - I have committed a new version which adds logic to check for duplicate usernames and also checks against users already in the system. This all occurs before it adds any users, so it should make for a much nicer experience. If you have a chance to test, please let me know how it goes. Screenshot showing when duplicates are detected Screenshot showing when existing users are detected
  13. When exporting a FieldtypeFieldsetPage using Setup > Fields > Export, repeater fields appears empty. Other repeater types (at least RepeaterMatrix) seem to export fine { "seo": { "id": 99, "type": "FieldtypeFieldsetPage", "flags": 0, // ... "repeaterFields": "", // empty "icon": "search", // ... } }
  14. For more tips, check out this blog post:
  15. I saw this once but I was lazy to make the adjustments will do later
  16. Hi @tpr Tiny issue today which was "discovered" by me long time ago, I just did not find the time to post it... Do you happen to have Forgot Password module installed? Button centering is missing here:
  17. No reason it would break at all. It's quite robust and a lot of corner cases are handled in the module source. But, regardless of your setup or page count, make frequent backups of your DB.
  18. Here you go <?php $nutritionMarkup = ''; $i = 0; foreach ($order as $o) { $item = $nutrition->get("name%=$o"); // skip if item or its name or value not populated if (!$item || !$item->name || !$item->value) continue; // increase the counter and assign left or right $class = (($i++) % 2 == 0) ? 'left-box' : 'right-box'; // to place two nutrition values in a wrapper, // open up wrapper before every even item if ($i % 2 === 0) $nutritionMarkup .= "<div class='nutrition-detail'>"; // markup for each nutritional value $nutritionMarkup .= " <div class='$class'> {$item->name}<br> {$item->amount} {$item->unit} </div> "; // close the wrapper after every odd item if ($i % 2 === 1) $nutritionMarkup .= "</div>"; } echo $nutritionMarkup;
  19. Awesome thanks for explaining it. I never seen that. However, everything seems to be working. just didn't want to get 1000 pages in and bam it breaks. this is going to be a big site and already exceeding 500 pages.
  20. Thanks @adrian Yesterday I actually "only" did some preliminary tests with around 50 users. It worked well but today I had to do the "real thing". I found that it was only about 33 users I could always create without timeout, more than that sometimes worked sometimes not. Since I had to deal with only about 150 users, I created them in groups of 33 or so, as I did not want to waste time with dealing with the timeout. My other issue was that I had to deal with duplicate user names. The batcher – in such a case – fails with mysql error (...Duplicate entry 'super_duplex_user' for key 'name_parent_id'...) which is not too elegant I cleaned up the CSV to tackle this but was wondering if the script could look for them in advance? Is that out of the scope of this action?
  21. Hi @horst, Im looking for an exact same solution, website is showing images, but can not be accessed through going directly to the URL. I tried your solution, but also the page where the image is displayed is getting a 404 response for this image. I also have de pwimg.php as a template and page /pwimg/ instead of a 'normal' php file, is that maybe a problem? I hope you can help me with this! Thnx.
  22. I'm glad it could help you! Yeah, in that case it is probably worth the regexp effort. When someone is not fluent in regular expression (like me ) it can be really time consuming to find the right rules if ever... But in the case of a reliable and well formatted source it is a lot easier to construct the expressions which work just right.
  23. This is actually so useful that I need to add to AOS (if you don't mind) Removing toolbar items is easy with your code but AOS may add extra buttons via CKEditor plugins. I found out that listing them in "removePlugins" is enough, so this can be used to remove extra plugins with ease: $this->addHookBefore('Field(inputfieldClass=InputfieldCKEditor)::getInputfield', function(HookEvent $event) { // do not show modified data on Field edit page if ($this->wire('process') != 'ProcessPageEdit') { return; } $field = $event->object; if($this->wire('user')->hasRole('editor')) { $field->toolbar = 'Bold, Italic'; $field->removePlugins = 'div, justify'; // plugins to remove $field->formatTags = 'p;h2;h3;h4'; // allowed format tags, separated with semicolon } });
  24. Repeater items are actually pages, and stored under /admin/repeaters/. If a template includes a repeater field, and you create a page using that template, a new repeater parent page is created under /admin/repeaters to house new repeater items for that specific page and a specific field. Changing the page's name or parent later on doesn't have an effect, because repeater parents use page and field ids for referencing which repeater items belong to which page and which field. <?php // FieldtypeRepeater.module /** * Return the repeater parent used by $field, i.e. /processwire/repeaters/for-field-name/ * * Auto generate a repeater parent page named 'for-field-[id]', if it doesn't already exist * * @param Field $field * @return Page * @throws WireException * */ protected function getRepeaterParent(Field $field) { $parentID = (int) $field->get('parent_id'); if($parentID) { $parent = $this->wire('pages')->get($parentID); if($parent->id) return $parent; } $repeatersRootPage = $this->wire('pages')->get((int) $this->repeatersRootPageID); $parentName = self::fieldPageNamePrefix . $field->id; // we call this just to ensure it exists, so template is created if it doesn't exist yet if(!$field->get('template_id')) $this->getRepeaterTemplate($field); $parent = $repeatersRootPage->child("name=$parentName, include=all"); if(!$parent->id) { $parent = $this->wire('pages')->newPage(array('template' => $repeatersRootPage->template)); $parent->parent = $repeatersRootPage; $parent->name = $parentName; $parent->title = $field->name; $parent->addStatus(Page::statusSystem); $parent->save(); $this->message("Created '$field' parent: $parent->path", Notice::debug); } if($parent->id) { if(!$field->get('parent_id')) { // parent_id setting not yet in field $field->set('parent_id', $parent->id); $field->save(); } } else { throw new WireException("Unable to create parent {$repeatersRootPage->path}$parentName"); } return $parent; } If you change the template and the new template does not have the same repeater field, then the repeater parent and all its items are deleted /** * Delete the given Field from the given Page * * @param Page $page * @param Field $field Field object * @return bool True on success, false on DB delete failure. * */ public function ___deletePageField(Page $page, Field $field) { $result = parent::___deletePageField($page, $field); $this->deletePageField = $field->get('parent_id'); $fieldParent = $this->wire('pages')->get((int) $field->get('parent_id')); // confirm that this field parent page is still part of the pages we manage if($fieldParent->parent_id == $this->repeatersRootPageID) { // locate the repeater page parent $parent = $fieldParent->child('name=' . self::repeaterPageNamePrefix . $page->id . ', include=all'); if($parent->id) { // remove system status from repeater page parent $parent->addStatus(Page::statusSystemOverride); $parent->removeStatus(Page::statusSystem); $this->message("Deleted {$parent->path}", Notice::debug); // delete the repeater page parent and all the repeater pages in it $this->wire('pages')->delete($parent, true); } } return $result; } As for your second question, I wouldn't worry as long as everything works fine
  25. Thanks for all the tips. I am aware of limit @mr-fan but thanks anyway. This is just a demo for now but will start writing some real content asap. Looking forward to being able to give something back to the community. Although my guides will probably be nothing new to seasoned users, they will make it easier for people new to PW, or maybe to persuade people choosing a CMS/CMF that PW is super easy to use even for non/beginner coders. Anyway, back from work now so can continue. -EDIT- I added a Datetime field to the blog posts with no output so I can choose the post date on each one rather than use the created date i.e. I can backdate them to make it look like I've been doing this for ages... seriously though, now it shows the two latest posts per category and I can manipulate the dates better (for HTML/CSS output) from the field timestamp. I'll probably stick that in a function as the date will be displayed on multiple templates. // category-index.php <?php namespace ProcessWire; ?> <div class="container"> <div class="row"> <?php $categories = $pages->get("/categories/")->children; foreach ($categories as $category): ?> <div class="col"> <h2><a href="<?= $category->url; ?>"><?= $category->title; ?></a></h2> <ul class="list-unstyled"> <?php $posts = $pages->find("template=blog-entry, categorySelect=$category, sort=-postDate, limit=2"); foreach ($posts as $post): ?> <li><a href="<?= $post->url; ?>"><?= $post->title; ?></a></li> <?= $post->summary; ?> <?php endforeach; ?> </ul> </div> <?php endforeach; ?> </div> </div> Seems to work ok: Thanks for all the help. Maybe my first post should be "How to make a blog with processwire"...
  26. Think I'm gonna need something like this for listing posts by date, thanks @ryan
  27. Hi Guys, I have been using Processwire for years now and have mastered enough to create some amazing sites and applications. However, recently I have been thrown a bit of a curveball and hoping some more veteran members can chime in. I recently ran into a weird issue. I had imported about 100+ wordpress pages into a new Processwire site using namespaces. I imported them under a parent page called /landing-pages/. However, I needed to move 20+ of these imported pages to a new parent page called /customers/. Since I was moving so many, I figured batcher was a solid module to run this task. Here are the steps I took: Located all the pages I needed using batcher Changed the pages templates Located the pages again after changing their template Made the pages hidden and then located them again using batcher Changed parent page from /landing-pages/ to /customers/ The issue that occurred is that not only did I change the parent page for these pages but apparently the pages also existed under /admin/repeaters/for-field-whatever which now changed to the new parent of /customers/. for-page-1625 admin /admin/repeaters/for-field-108/ So I reverted this by using batcher again, here are the steps I took: Located all the pages that were not supposed to be moved Changed the pages parent back to /admin/repeaters/ The issue is, after this was done, every time I clicked the new page under /customers/whatever-page I would get a 404. To correct this I had to delete all the pages under /admin/repeaters/ and /admin/repeaters/for-field-whatever and then go back and delete the pages under /Customers/ and create them all from scratch. My questions are: Why did Processwire create pages under /admin/repeaters for the imported pages? The steps I took to correct this issue, is this okay to keep building the site or am I better off starting fresh again?
  1. Load more activity