• Content count

  • Joined

  • Last visited

  • Days Won


BitPoet last won the day on December 31 2016

BitPoet had the most liked content!

Community Reputation

1,123 Excellent

1 Follower

About BitPoet

  • Rank
    Hero Member

Profile Information

  • Gender
  • Location
    Near Munich / Germany
  • Interests
    programming, writing, scuba diving

Recent Profile Visitors

3,740 profile views
  1. That's probably because MySQL strict mode is enabled. sortRebuild() uses a "shortcut" notation for multiple updates using an "INSERT ... ON DUPLICATE KEY UPDATE ..." statement that fails in strict mode. Both disabling strict mode globally or adding the following in site/config.php should help: $config->dbSqlModes = array( "5.5.0" => "remove:STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY" ) This is already the default for MySQL >= 5.7, but both features may be active in 5.5 and 5.6 installations as well. There's already an open issue for this here.
  2. You could either remove the page-add permission from the role completely or remove the "add children" permission in the page's template for the exponent role.
  3. Reading and writing times shouldn't be (noticeably) influenced by the pure size of a volume (unless the physical disk underneath is nearing the end of its capacity or the underlying FS becomes highly fragmented). Enumerating large number of entries (files/subdirectories) in a single directory would likely be a factor, so if you have more than 10k pages, breaking up the flat hierarchy of site directories could be worth thinking about - but even then, structuring them by year wouldn't be my first approach as it is counter-intuitive and has a number of pitfalls (e.g. timezone changes, duplicate files when overwriting, code that assumes all files for a page can be found in the same directory). Here's an example that adds a three-digit parent directory based on the page id that could be a starting point. It ignores the pageFilesSecure option, so be careful with it. You can look at PagefilesManager::___path and Pagefilesmanager::___url how they deal with that and other "magic". Of course, instead of that purely id-based dir, you can have the getPageSubdir function return anything you like. If you want to split your data between volumes, it could just return "old" for page ids < 5000 (or whatever the latest page id on the old volume is) and "new" for those above. /* * Change files path, insert a three-digit directory above, left-padded * with zeroes. This way, there won't be more than 999 directories under * site/assets. * * Subdirectory count won't be an issue unless you cross the million pages * mark. */ wire()->addHookAfter("PagefilesManager::path", null, "modifyPath"); function modifyPath(HookEvent $event) { $p = $event->return; $p = preg_replace_callback('~^(.*/)([^/]+)/~', function($match) { return $match[1] . getPageSubdir($match[2]) . "/" . $match[2] . "/"; }, $p); $event->return = $p; } wire()->addHookAfter("PagefilesManager::url", null, "modifyUrl"); function modifyUrl(HookEvent $event) { $url = wire('config')->urls->files . getPageSubdir($event->object->page->id) . "/" . $event->object->page->id . "/"; $event->return = $url; } function getPageSubdir($id) { return str_pad(substr($id, 0, 2), 3, '0', STR_PAD_LEFT); }
  4. It was far easier than I had first expected, as I started without much external input and CI restraints, so I could stick with UIKit defaults and had no usability expectations to meet. So I stuck with the "keep it simple" philosophy. I'm tentatively planning to make a release bundle out of it (time is as always the factor), but need to strip out a few specifics first and replace them with more generic code. There are also a few things which I simply stuck into site config but would merit a dedicated config page (think addresses, currency, holidays, time constraints and all that).
  5. Between a lot of big, not-web-related projects at work, I could squeeze in having a little a fun with ProcessWire too. What was needed was a shop-like solution where employees can order lunch snacks from our local butcher. Previously, this was handled with hand-written lists in each production hall that would be forwarded over fax to the butchers, leading to all kinds of transliteration and pricing errors. Our Central Services department looked at different software packages for that, but none of them did exactly what they needed. ProcessWire to the rescue. In little more than two days, I got a fitting solution up and running: PW 3.0.52 The only two non-standard modules used are @adrian's AdminActions and my own DatetimeAdvanced Role based template access UIKit 3 with modals, flex layout, mobile-ready with hamburger menu on smaller devices Everything is a page Synchronisation of employee accounts from time management software (> 600) into PW (120 lines, runs twice a day) Mixed authentication (Windows Active Directory if user is available there, local password if not) Account balance system with manual deposits and automated checking / detuction / refunding for orders, complete transaction history visible for the user Article categories (page reference), product images (not used yet), simple product variants (1 level, text + price) Ordering contents of a shopping cart for a single day or multiple days ahead of time within (admin configurable) time constraints (order window for following day ends X hours before, holidays excluded, etc.) Delivery locations (buildings) changeable by users themselves Integrated favorites system Management area in frontend for balance bookings, managing articles, previewing orders Daily collected orders for the butchery are printed into PDF through fpdf with a tiny wrapper Product images option with thumbnails (currently not used) Small additions like price validity dates or saving and re-using shopping carts will be added over the next months The shop landing page with all relevant information: Articles are grouped by category and have dropdowns for variations (with optional price addition/discount): Editable shopping cart with option to order same selection for multiple days: Minimallistic product item editor:
  6. Untested, but it might be possible to change the template object's noMove property before and after moving the page: <?php $nomove = $page->template->noMove; $page->template->noMove = false; $page->of(false); $page->parent = $pages->get('/my/new/parent/'); $page->save(); $page->of(true); $page->template->noMove = $nomove;
  7. Is opcode caching active on those sites (opcache, APC)? If yes, one of those could be responsible. If the site used opcache, make sure that opcache.validate_timestamps is true, for APC make sure that apc.stat is enabled.
  8. Loading of regular pages might benefit a tiny bit from using my module, but managing images would still be prone to the same delays if you put all images into a single library (which is just a page behind the scenes). You might still be able to make use of it if you can separate images into different libraries (e.g. by categorizing them into logos, photos, product images etc.) so numbers stay manageable. Media Library uses PW's native tools (file/image fields, CKEditor pwimage plugin), and I have to admit, I haven't tested those (and my module) with a big number of images - the module is a result of an internal requirement at work, where the number tends to stay well below 100. I'd say give it a quick try in a test system (perhaps in conjunction with the FileFieldTweaks option of @tpr's AdminOnSteroids). If you find you need something more elaborate though, @kongondo's Media Manager pro module might be worth a look.
  9. You have to perform the check for the template name inside your hook function. $this->page or wire('page') returns whatever page in which the module code is executed (admin page editor, custom page with the code...). Pages::save on the other hand is called with the page object being saved, which is what you're looking for. public function init() { $this->pages->addHookAfter('Pages::save', $this, 'syncMobileDE'); } protected function syncMobileDE(HookEvent $event) { $page = $event->arguments(0); if($page->template->name == 'TemplateName') { // Run your code } }
  10. <?php $pagearr = $pages->newPageArray()->add($page->myfield);
  11. You can hook before ProcessLogin::executeLogout and set the desired url. <?php wire()->addHookBefore("ProcessLogin::executeLogout", null, "setRedirect"); function setRedirect(HookEvent $event) { $event->object->setLogoutURL($pages->get('/')->httpUrl); }
  12. Since I am the one guilty of adding UTF-8 support to WireMail, I could take an educated guess WireMailSmtp uses some external libraries that have evolved over the years and have their own routines to handle character encoding in address headers. I'll take a look at what is done differently there (I have an idea, but I'll have to run some tests to be sure) . In the meantime, if using wireMailSmtp is an option, I'd go with that.
  13. Could you try and shorten the fromName and toName (or replace it with plain ascii ones) for testing and see if that fixes it? It might be a line wrapping issue in one of those two.
  14. Is the first line complete? The missing from: header start and quoted-printable preamble is the only thing I see that's incorrect. If it's not, can you make sure that there are no line breaks in the fromName? setLocale shouldn't have any influence on WireMail's behavior.
  15. So the fields are named Tab1...Tab9 resp. TabContent1...TabContent9? In that case, two possibilities immediately come to mind, but both require you to assemble the name outside of the quotes (there might be a way inside the strings, but I can't think of one right now). <?php //... $tabname = "Tab" . $i; echo "<label for='tab{$i}' class='labeltab'>{$page->$tabname}</label>\n"; Or, in one go: <?php //... echo "<label for='tab{$i}' class='labeltab'>" . $page->get("Tab" . $i) . "</label>\n";