Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by BitPoet

  1. Hi @Ivan Gretsky, I will at one point for sure, but that will be late in the year. I‘m currently hiking across the U.S. and won‘t get my hands on a computer until October.
  2. You'd need to turn Event and EventArray into modules programmatically, i.e. add "implements Module" to the class declaration and add the static getModuleInfo() method. The returned array from that method is where you can set the autoload value. Then you can also drop the require_once() statements in the fieldtype's constructor. (And don't forget to install Event and EventArray Modules in the backend after the change)
  3. I'm not sure I'd go down that road, even though it's probably possible. For one, you can't take advantage of the logic already there for numeric field types. For two, what if there are additional price scales? To round it up, for three, it may speed up input, but there will likely be cases where you'll have to disassemble the unformatted value anyway to present the information. I'd go with a repeater that has fields for quantity and price (maybe a default price field on the item page and just add scale prices in the repeater). That way, your data is queryable through selectors, your code will be easier to understand years later when you have to come back and make changes, and you don't have to worry about multiple scales for one item. Price calculation will be just a small piece of code: $price = $item->price; foreach($item->scaleprices->sort('-quantity') as $scale) { if($order->quantity >= $scale->quantity) { $price = $scale->price; break; } }
  4. Have you tried calling $modules->get('yourfieldtype') before using the API? To avoid that, you could turn Event and EventArray into autoload modules.
  5. The wrong is on the side of the module. Too much has changed in the standard datetime field, and I didn't have the time to catch up with these changes. You'll probably have to remove the field and module by hand on the database level (there could be easier ways, but the exact approach probably depends on the exact PHP and PW versions). drop the table field_[yourfieldname] execute the query "DELETE FROM fields WHERE type = 'FieldtypeDatetimeAdvanced';" execute the query "DELETE FROM modules WHERE type = 'FieldtypeDatetimeAdvanced';" delete the module directory Sorry for the hassle. I have added a notice to the module's readme. Unfortunately, I won't find the time to adapt the module before the end of the year.
  6. In site 1, I'd guess that there's a spot where you're missing quotes in $_SERVER['HTTP_HOST'] (i.e., $_SERVER[HTTP_HOST], which will with strict mode turned off interpret HTTP_HOST as the name of a constant in the current namespace). The error in site 2 points to a missing pdo_mysql extension, so make sure that it's activated and enabled in php.ini.
  7. I think we've talking past each other a bit, so let me see if I can word it differently. The cache should never return an expired value, but I can understand that the strange behavior in your tests 5 and 6 suggests differently. If you don't want to lose a value, don't let it expire. Instead, put the logic to overwrite the cached value with a newer one when your API call is successful into your code. And perhaps store the last retrieval time in your cached value, so you have the creation timestamp you mentioned. Perhaps code says more than a thousand words: <?php /** * Code for Cron Job */ $apiResult = your_api_call(); $cachedResult = json_decode($cache->get('yourcachekey'), true); if($apiResult) // Only if API call was successful if(!$cachedResult || $cachedResult['created'] < time() - 300) { // Cache entry older than 5 minutes, write new value to cache $cache->save('yourcachekey', json_encode(['created' => time(), 'apiResult' => $apiResult], WireCache::expireNever); } } /** * Code for frontend use of API data */ $cachedResult = json_decode($cache->get('yourcachekey'), true); $apiResult = $cachedResult['apiResult']; if($apiResult['created'] < strtotime('-1 month')) { // Deal with a stale cache value that hasn't been updated in over a month here }
  8. Nice overview! For full fledged field types, you'll often also want to implement Fieldtype::getConfigAllowContext and Inputfield::getConfigAllowContext. They return an array with the names of those config fields defined in their respective getConfigInputfields method that may be overridden in template or fieldgroup context. The Inputfield class by default returns these config fields: return array( 'visibility', 'collapsed', 'columnWidth', 'required', 'requiredIf', 'requiredAttr', 'showIf' ); So make sure to call parent::getConfigInputfields first, then add your own config inputs. A good example is how InputfieldText does this: public function ___getConfigAllowContext($field) { $a = array('initValue', 'pattern', 'placeholder', 'maxlength', 'minlength', 'required', 'requiredAttr'); return array_merge(parent::___getConfigAllowContext($field), $a); } Now the initValue, pattern, placeholder, maxlength, required and requiredAttr settings can be overridden in each template the field is used in.
  9. In that case, the most straight forward approach is to add a custom permission through the backend (e.g. 'import-pages'), hook before your module's execute method and check if the current user has this permission. Untested code for site/ready.php: <?php namespace ProcessWire; wire()->addHookBefore("ImportPagesCSV::execute", function(HookEvent $event) { if(wire('user')->isSuperuser() || wire('user')->hasPermission('import-pages')) return; $event->return = '<h3>You do not have permission to import pages. Please contact the administrator!</h3>'; $event->replace = true; }); Of course, this still leaves the backend menu item in place, but unlike modifying third party modules, it is upgrade safe.
  10. The word "tag" is very a technical thing. Call them "keywords" instead, and more than half of your users' questions will evaporate instantly. That's what I learned at my current job when I trained colleagues and heard the relieved insight, "Oh, you're talking about keywords!" rather often. The other half you'll only catch with real-life examples. Depending on the number of pages and content editors, it might make sense to moderate keywords for a while until everybody got their footing. Just a small Pages::published hook that sends a backend link to the new page to the tags moderator so they can give the chosen tags a once over and clarify with the editor what makes sense and what doesn't. I did that with a small knowledge base section for our technical sales managers when they went into a new market area, and we used the direct feedback to fill the tags (later keywords) FAQ with examples and explanations that made sense to them. Actually, that's no longer the case. Since 3.0.177, you can use the new InputfieldTextTags, and choosing a delimiter other than space will allow multi word tags.
  11. As a hobby writer, I do have my doubts there. Natural language is the second most ambiguous thing in the world, right after Schrödinger's cat.
  12. Why don't you split your cron job's logic to use two separate cache calls? $cache->get('cachetest') to read your cached data without expiring it, and $cache->save('cachetest', '+1 month', $apiresult) only if your api call was successful. You'll always have the last successful call's result in your cache this way, and it will be much cheaper than full fledged pages.
  13. I'd say it's just a question of a missing "echo" in front of page()->render('callout');
  14. The short answer is: don't use a lifetime in calls to $cache->get(). Somewhat longer: it looks like a bug to me. It certainly doesn't do what the docs say, namely check the age of an entry. The behavior is a bit different if you specify a template function as the third value, as that uses the lifetime to fill the cache with the function's return value, but that's neither here nor there. In your case (unless I'm misinterpreting what you wrote), the only call that needs a lifetime is the one to $cache->save() in your cron job. The other parts can just call $cache->get('cachetest') and be happy (unless the cache wasn't updated within the last month).
  15. is_callable doesn't resolve namespaces. It should work if you use "ProcessWire\\custom_debug_if". I'm not sure why ProcessWire.php doesn't use wireIsCallable() at that spot. Might be worth raising an issue.
  16. Also, make sure that your search form and results template use the correct request method (GET vs. POST), as having "<form method='POST'>" in the HTML and reading $input->get->q in PHP would explain the behavior.
  17. It's very likely, as this post in the module's support thread suggest: I'm not familiar enough with ProcessChangelog (nor ProcessDatabaseBackup) to guess at the technical issue behind that, but maybe @teppo as the module's author can shed some light on it.
  18. More likely memory_limit, not post_max_size. The first thing I'd try is to uncache pages in your executeAction method, but if your database is huge (any kind of logging going on like ProcessChangelog?) upping memory_limit might be the way to go.
  19. As @Jan Romero wrote, its more often than not that a link's textual information is generated dynamically from its relationship (e.g. the page/template it's on or that's referenced). For manual entry of link texts, creating separate fields for the link target and the text like you did is the way to go. You can, however, make your developer life easier when you have multiple occurrences of that combination in different templates by wrapping both in another field type. This can be a Repeater if you have multiple entries, or for a single one you can use either FieldsetPage or FieldsetGroup, depending on whether you want the link entry to live under a unique property of your page. With fieldsetgroup it is $page->urlfield and $page->linktextfield, while in fieldsetpage its $page->myfieldsetpagefield->urlfield and $page->myfieldsetpagefield->linktextfield. The former is more performant, while the latter makes it more clear that both fields are related.
  20. Or install @tpr's AdminOnSteroids module which, among many other really convenient shortcuts, adds a "clear" button to PageListSelects.
  21. What's the error message you get? Maybe a stupid question, but did you enable .heic in the image field's allowed extensions?
  22. That's strange. Somewhere along the way, PagePathHistory::__upgrade should have been triggered and added that column. The language_id column was introduced with version 2 of the module, shortly before PW was moved to the new GitHub repo in 2016. There was an identical issue mentioned back then, and Ryan added a self-healing fix in PagePathHistory::getPath, but it looks like he took that out after a few years. You can, however, add that column manually to get rid of the error and put the language_id back into the select: ALTER TABLE page_path_history ADD language_id INT UNSIGNED DEFAULT 0
  23. Behind the scenes, the admin user is a page with the id 41, so you can determine the username by running the following sql query: select `name` from `pages` where `id` = 41; The quickest way to reset the password should be this:
  24. You're inside a function, so there's no global $datetime object. wire('datetime') should do the trick.
  • Create New...