Jump to content

BitPoet

Members
  • Posts

    1,325
  • Joined

  • Last visited

  • Days Won

    60

Everything posted by BitPoet

  1. Or it might be sufficient to replace the module in question (ProcessWire Upgrade) in site/modules with the recent one which doesn't have that issue.
  2. preg_replace('~(<h[23]\\b.*?>(?:<[a-z][^>]*>)*)(\w+)~ism', '$1<span>$2</span>', $headline); quick&dirty in PHP
  3. The theme itself should be the last piece you think of editing, as you will invariably detach yourself from future improvements that come with the regular updates. Almost everything can be done by using existing modules or, for very specific requirements, by extending other modules or writing your own that work within the theme (and still do when you switch to another theme). Have a look at @Soma's Page List Image Label module as @dragan suggested. The commercial Lister Pro module might also be worth a look. With it, you can create flexible page lists and add them to the menu for your editors. There are nice screenshots here, for example. It should be possible to add these listers to the main menu level too. You can even build your own Process modules to extend the backend, which is quite straight forward. You can find a good introduction in the PW blog. You can add custom fields to your User template, and the configuration (Setup -> Configuration) of ProcessUser lets you select which of those are visible in the user list. Changing the buttons in the page tree can be done through hooks on methods in ProcessPageList and ProcessPageListActions (e.g. inside site/ready.php, which is update-safe) and, on the visual side, by adding your own custom js and css (e.g. through the Admin Custom Files module).
  4. 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.
  5. 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 */); })
  6. 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; } }
  7. Did you adapt the SMTP settings in php.ini? It might be configured to use sendmail by default.
  8. 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.
  9. 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.
  10. 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.
  11. 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.
  12. 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.
  13. 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.
  14. 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?
  15. 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.
  16. 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
  17. 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?
  18. Does it still persist if you delete the contents of site/assets/cache/FileCompiler?
  19. Adding a /*NoCompile*/ FileCompiler hint as explained here should solve the issue (and let you keep FileCompiler active).
  20. Hm. sku_image is definitely not contained in p21fields? The line below is apparently the only one that modifies the page's field values, so still the most likely suspect (unless there's more in the code you left out or some hook magic somewhere else). Maybe outputting $field to the log can shed some more light there. Also, check compareData for singe/double equal sign mixup in if conditions. $p->set($field, $data[$ctn]);
  21. That would probably the relevant part that we would need to see to make an educated guess. Does the script perchance replace the Pageimage object assigned to sku_image with an empty one?
  22. Looks like you need to include jquery in your page (see point 4 in the lightbox2 getting started docs).
  23. Is your include file namespaced? If not, throw new \ProcessWire\PageNotFoundException(); should do the trick. Or adding "namespace ProcessWire;" at the top, obviously.
  24. Perhaps PW's core PagesExportImport fits the bill there. The result is quite verbose and more nested though since it includes everything needed to recreate a page. $myPages = $pages->find('template=catalog-item'); $PEI = new PagesExportImport(); export $PEI->exportJSON($mypages); To get array data instead of a JSON string, call pagesToArray instead of exportJSON.
  25. Nginx' performance advantages over Apache were built on three factors: modern-day multiprocessing in the server, a lot less overhead due to reduced functionality and memory caching. Over the last five years, Apache has greatly reduced that gap by adapting Nginx' multiprocessing approach (one keyword there is the event MPM module), so Apache isn't spending most of its time spinning up and tearing down whole server instances anymore. File system access has greatly improved with solid state disks, too. Apache still has a lot more functionality, and its distributed config file approach, most prominently the ability to make configuration changes with a .htaccess file inside the web directories, hurts performance. Its dynamic module loading approach and the dozens of pre-installed modules most distributions ship also take up processing time and memory. Nowadays, Apache can be stripped down a lot and compiled to be head to head with Nginx, though few actually care to do that, since it also means removing functionality one might need in the future. A stock Apache is usually still quite a bit slower and reaches its limits faster (about the factor 2). This becomes an issue under heavy load or on slow machines. Where Nginx still shines brightly is load balancing. Apache can do it too, but with Nginx it is straight forward and well documented, having been there for a long time. For those interested in a bit of (highly subjective) history: for a long time (speak eighties and nineties), the classic forking mechanism that was common on *nix OSes was the way to do multiprocessing in network servers, and therefore in Apache too. This meant spawning a full copy of the server process and initializing it, then tearing it down when the request was done. Apache brought a small revolution to that approach by implementing preforking, meaning to keep spare server instances around to fulfill requests with little delay. After a while, there were other approaches too when faster multiprocessing approaches become part of common operating systems, like multi threading, which is supported by Apache's "worker" multiprocessing module (MPM). There were, however, big caveats with using other MPMs. Since file systems used to be slow, sometimes awfully so, in the old days, and since the classic CGI approach of starting an executable from the file system, supplying it with information through environment variables and standard input and capturing its standard output was a security nightmare - even without thinking about shared hosting - nifty programmers included full languages interpreters inside Apache modules. mod_perl and mod_php became the big thing, the latter coming to dominate the web after a few years. These interpreters, though, often had memory leaks and issues with thread isolation, meaning at best that an error in one thread tore down numerous other sessions and at worst that the server had a propensity for information leaks, remote code execution and privilege escalation attacks, the former security nightmare squared. Thus, these tightly integrated interpreters more or less locked their users into the classic prefork approach where every instance is its own, basically independent process. With PHP as the market leader not evolving in that regard, things were frozen for quite some time. This was when Nginx conquered the market, first by serving static HTML and associated resources with lightning speed (CMSes generating static HTML were still a big thing for a while), but soon by taking care of all the static stuff while handling the dynamic things off to Apache and caching parts of its responses in memory. Finally, though, PHP finally got a fresh boost and grew stable enough for its engine to re-use interpreter instances. It was easier to contain things inside an interpreter-only process instead of dealing with all the server peculiarities, so FastCGI daemons finally became stable, known and used, and suddenly the need to have the language interpreter contained in the web server fell away. Apache got leaner and Nginx more flexible. Caching servers like Varnish became popular since it suddenly was relatively easy to build a fast, nice, layered caching solution with a combination of Nginx, Varnish and a full fledged web server like Apache or IIS, able to serve thousands of highly dynamic and media rich pages per minute. About that time, SSL grew in importance too, and hosting providers learned to love Nginx as a means to route domains to changing backends and provide fast and easily configurable SSL endpoint termination. Over the last years, Nginx got other features like generic TCP protocol load balancing that offset it from other servers and make it more into a one-stop solution for modern web applications. It does boost its popularity that Nginx is often the first (or the first major) web server to ship evolving technologies, making the front pages and pulling in early adopters, http/2 being one of the most prominent examples there.
×
×
  • Create New...