Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


BitPoet last won the day on September 15 2019

BitPoet had the most liked content!

Community Reputation

2,273 Excellent


About BitPoet

  • Rank
    Hero Member

Profile Information

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

Recent Profile Visitors

6,568 profile views
  1. You can add your own validation with a small hook in site/ready.php. wire()->addHookAfter("InputfieldDatetime::processInput", null, "validateFuture"); function validateFuture(HookEvent $event) { $field = $event->object; // Make sure to enter the correct name of your field here: if($field->name == "crondate") { // Compare field with current time plus 30s * 1000ms: if($field->value < time() + 30000) { $field->error("Date is not in the future!"); } } } Adapting the datetimepicker isn't easy if possible at all.
  2. Just one, I think. document.querySelectorAll returns a NodeList. Unlike with jquery collections, you can't call addEventListener on the NodeList but rather need to iterate over its elements and attach a listener to each one. Array.forEach.call(nodeList, function(el) { el.addEventListener(/* your class toggle code here */); })
  3. I'm not familiar enough with Carbon to make a guess how well DateTimeAdvanced works with it. Generally, every operation/function call that expects a string should still work the same as with a regular Datetime field when output formatting is off, since my helper object has a ___toString() method that returns the unix timestamp. If you just want to add database subfield selectors to your system and don't want to search arrays or plug in your own subfield patterns, you can use this stripped-down module: <?php /** * ## Enhanced Datetime Field * * Allows searching for individual components of datetime fields in * standard subfield syntax in the database. * * Note that this doesn't work for searching in PageArrays. For that, * use the DatetimeAdvanced Fieldtype instead. * * ## Possible subfields * * - day * - month * - year (4-digit) * - hour (0..23) * - minutes * - seconds * - day_of_week (0..6, 0 = Sunday) * - day_of_year (0..365) * - week_of_year (1..53) * - date (just the date part, yyyy-mm-dd) * - time (just the time part, hh:mm:ss) * * ## Example * * ``` * $pagelist = $pages->find("mydatefield.year=2016"); * ``` **/ class FieldtypeDatetimePlus extends FieldtypeDatetime implements Module, ConfigurableModule { public static function getModuleInfo() { return array( "title" => "Datetime Plus", "summary" => wire()->_("Datetime field with extended search syntax. Needs timezone support enabled in MySQL, see http://dev.mysql.com/doc/refman/5.7/en/time-zone-support.html for details."), "version" => "0.0.1" ); } protected static $_operators = array( "day" => array("d", "d"), "month" => array("c", "m"), "year" => array("Y", "Y"), "hour" => array("H", "H"), "minutes" => array("i", "i"), "seconds" => array("s", "s"), "day_of_week" => array("w", "w"), "day_of_year" => array("j", "z"), "week_of_year" => array("v", "W"), "date" => array("%Y-%m-%d", "Y-m-d"), "time" => array("T", "H:i:s"), ); /** * Match a date/time value in the database, as used by PageFinder * */ public function getMatchQuery($query, $table, $subfield, $operator, $value) { if($subfield != "data") { if(! $this->isAllowedSubfield($subfield)) { throw new WireException(sprintf($this->_("Unknown subfield name for datetime field: %s"), $subfield)); } if($subfield == "date" || $subfield == "time") { $value = preg_replace('/[^0-9:-]/', '', $value); } else { $value = $this->sanitizer->int($value); } if($operator == "day_of_year") { $value += 1; } $database = $this->wire("database"); if($database->isOperator($operator)) { $table = $database->escapeTable($table); $value = $database->escapeStr($value); $formatarg = self::$_operators[$subfield][0]; $formatarg = preg_replace('/([a-zA-Z])/', '%$1', $formatarg); $query->where("DATE_FORMAT({$table}.data, '{$formatarg}'){$operator}'$value'"); } } else { $value = (int) $this->_sanitizeValue($value); if($value) $value = date('Y-m-d H:i:s', $value); else $value = ''; $database = $this->wire('database'); if($database->isOperator($operator)) { $table = $database->escapeTable($table); $subfield = $database->escapeCol($subfield); $value = $database->escapeStr($value); $query->where("$table.{$subfield}{$operator}'$value'"); } } return $query; } public function isAllowedSubfield($subfield) { return array_key_exists($subfield, self::$_operators); } public function getInputfield(Page $page, Field $field) { $inputfield = $this->modules->get('InputfieldDatetime'); $inputfield->class = $this->className(); return $inputfield; } /** * Return array with information about what properties and operators can be used with this field. * * #pw-group-finding * * @param Field $field * @param array $data Array of extra data, when/if needed * @return array See `FieldSelectorInfo` class for details. * */ public function ___getSelectorInfo(Field $field, array $data = array()) { if($data) {} $selectorInfo = $this->wire(new FieldSelectorInfo()); $info = $selectorInfo->getSelectorInfo($field); foreach(array_keys(self::$_operators) as $op) { $info["subfields"][$op] = array( "name" => $op, "label" => $op, "operators" => $info["operators"], "input" => "text", "hint" => "", "options" => array() ); } return $info; } public function ___getModuleConfigInputfields() { $ifs = new InputfieldWrapper(); $cmd = $this->config->dbInitCommand; $off = date('O'); $needUpdate = false; if(strlen($off) > 0) { if(preg_match('/time_zone/i', $cmd)) { $needUpdate = false; return $ifs; } // PHP returns +0200, MySQL wants +02:00 $off = preg_replace('/(\d\d)$/', ':$1', $off); // Append timezone set statement $cmd .= sprintf(", time_zone = '%s' ", $off); } $f = $this->modules->get("InputfieldMarkup"); $f->label = $this->_("Enable timezone support in MySQL"); $f->description = $this->_("For datetime plus database selectors to be reliable, PHP and MySQL need to add/subtract the same offsets for datetime and timestamp values.") . " " . $this->_("To accomplish that, the timezone setting in MySQL needs to be set to the same value as in PHP.") . " " . $this->_("Copy the following line to site/config.php:") ; $f->attr( 'value', "<code>" . "\$config->dbInitCommand = \"$cmd\";" . "</code>" ); $f->notes = $this->_("Important: timezone data must be loaded in MySQL! See [this link](http://dev.mysql.com/doc/refman/5.7/en/time-zone-support.html) for details."); $ifs->append($f); return $ifs; } }
  4. Did you adapt the SMTP settings in php.ini? It might be configured to use sendmail by default.
  5. I need to take a look at that, but unfortunately, I'm not hopeful that I'll find enough time this week. Next week should be a bit less crazy though. I haven't found the time to update to the latest FB release, but it looks like soon will be a good time to do so 🙂 Stay tuned.
  6. If you plan to go live with validation email enabled anyway, it would also make sense to use a dummy SMTP server like FakeSMTP. That way, no mail is actually sent out but you have an instant preview, can save all mails to files, view those in your mail application and test the validation links inside.
  7. Thanks for letting me know. Fixed in 0.1.5, already on GitHub and soon in the module repo. I'm pretty sure I caught all translation call issues now.
  8. Behind the scenes, repeater entries are individual pages, so when you iterate over an entry (your second loop), you iterate over all the properties of the repeater page. You can see that if you change your code to: foreach ($child->Portrait_Repeater as $data) { $i = 1; foreach($data as $prop => $person_data){ $content .= $i.": $prop => ".$person_data."<br />"; $i++; } } The solution is to remove the inner loop and address the properties by name instead, like $person_data->email, $person_data->position etc.
  9. Thank you for the feedback. I have merged the change into the main branch, so once 0.1.4 hits the module repository (should be within the next 24 hours) it will be fixed the official package too.
  10. I've had some strange issues recently with pages that had a parent template restriction in the family settings and moving/creating them parent pages that in turn had a child template family restriction. Unfortunately, I didn't have time to investigate this further and just removed one of the restrictions to get things working again.
  11. Good point. If PHP is configured correctly in that regard, you should be able to use date() to set it dynamically. $config->dbInitCommand = "SET NAMES '{charset}', time_zone = '" . date('P') . "' "; I think there was a reason why I didn't try to convert the configured timezone to an offset, but I need to check that. Definitely not intended. That should be taken care of by the Modules class. Did you get any warning messages while uninstalling the module?
  12. Not out of the box. For requirements like this, I usually use a regular text input with a showIf (perhaps also requiredIf) dependency on the "other" option.
  13. It should be possible. You can use the methods of InputfieldWrapper on the return value of buildFormContent, retrieve the field by name, create the new Inputfield and insert that in the place of the original one with insertBefore()/insertAfter() and remove(). //... $wrap = $event->return; $origFld = $wrap->get('parent_id'); $newFld = wire('modules')->get('InputfieldPageAutocomplete'); $newFld->attr('name', 'parent_id'); $newFld->attr('value', $origFld->attr('value')); // do any other instantiation work, like setting/copying title, label etc. $origFld->parent()->insertAfter($newFld, $origFld)->remove($origFld); // done
  14. Looks like the plain _() translation method is not available anymore for some reason (perhaps something to do with the changes in the function API that I didn't catch). Could you try out the version at this link and let me know whether that fixes it for you?
  15. Does it still persist if you delete the contents of site/assets/cache/FileCompiler?
  • Create New...