Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


BitPoet last won the day on July 9

BitPoet had the most liked content!

Community Reputation

2,417 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,883 profile views
  1. Unfortunately not. The mysqli wrapper uses the object oriented interface, so there isn't even an easy point to add that part in the core library between instantiating the module and invoking mysqli_real_connect(). Your best bet is to look at the stack trace to see which module causes the dump (enable $config->debug in site/config.php) and either find a replacement or post an issue in the module's git repo to get it converted to PDO.
  2. Is the repeater set to Ajax load? If yes, you may have to look into the network tab of the browser's developer console for the ajax request. The server's response to that should give you more of a clue.
  3. Since your Page::changed hook is called, trackChanges already appears to be enabled. Have you tried getChanges(true) inside a saveReady hook? Also, the change information should be visible in arguments 1 and 2 in a Pages::saved hook.
  4. Using SSL should be quite straight forward, assuming that everything is configured correctly on the server side. The enforcing happens on the server the moment you issue an ALTER USER your-processwire-user@your-mysql-server REQUIRE SSL The moment you do that, you'll get a database error when you access your site. To enable PHP to talk over an encrypted MySQL connection, you now need to point it to the MySQL server's CA certificate. Copy that to a location where the web server can read it and add an entry in site/config.php (adapt the path to match your ca cert location): $config->dbOptions = array( \PDO::MYSQL_ATTR_SSL_CA => 'C:/temp/mysql-ca.pem' ); There may be scenarios where the name you use to access the server doesn't match the name in the certificate and you get the error "SQLSTATE[HY000] [2002]". The same error occurs when you use a self-signed certificate in the server (that's the case when you leave things to default after installing MySQL on most distributions). In that case, you need at least one of the following PHP versions: PHP 7.2, 7.3, 7.4 or 8 all versions PHP 7.1 >= 7.1.4 PHP 7.0 >= 7.0.18 The reason is that earlier versions of the MySQL PDO module didn't have the flag to disable certificate verification. You need to expand your entry in site/config.php: $config->dbOptions = array( \PDO::MYSQL_ATTR_SSL_CA => 'C:/temp/mysql-ca.pem', \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false ); Most (hopefully all) PW modules should be using the PDO interface by now, but you may stumble upon one that still makes use of the old mysqli wrapper. Those won't work with an SSL connection.
  5. That. The main.css under site/templates/assets/css is meant as a convenient place to add custom styling (no sass/less magic involved here). I had meant to change that time() call to an mtime() call as an example of how to bust the cache whenver the file is changed, but I apparently never got around to it. Brushing up my site templates is another point on my growing todo list. The default styling is done in site/templates/assets/css/blog.css, but you won't see that filename in the developer console because the site template uses the AOIM module to combinde and minimize the js and css files.
  6. Hi HerTha, sorry I couldn't respond sooner. This looks like the "link" field is a page field, am I right there? In that case, it doesn't work right now as you'd need something like "link->url" in the mention columns, which isn't supported yet. Only direct properties of the found pages can be used. I'm going to meditate on it, but I can't promise a quick solution.
  7. BitPoet


    I live on the countryside too, but I had to travel to another town to restock toilet paper on Friday because every single one of our eight supermarkets and drug stores was out of stock. I finally got a pack (one out of the last three) in a neighbor town. People are hoarding like crazy. I saw a few customers with trolleys heaped with paper towels and pasta. Stupid. But if you look at the run for toilet paper, you know what's in their minds... But yes, most people around here are both realistic and calm, thankfully. At work, we have a revolving home office schedule now in most departments to make sure that we can have staff on site in case those present at the office have to quarantine. Business is slowing down because negotiation meetings can't happen in person. But all that (as always in changing circumstances) means more work for our department for now to get as many colleagues as possible set up to work from home, i.e. additional VPN lines, laptops, remote desktops, e-learning, conferencing software etc. All things which we were already rolling out to everyone, but what was planned over the course of a year now has to happen within days and on top of ongoing major projects. So the weekends are going to get even shorter, and instead of implementing planned features in software, it's now more about tying things together to get everybody's remote work experience to lift off flawlessly. For me personally, things got turned on the head because I was about to start the last four weeks of work before my half year sabbatical. After years of planning, I was about to thru-hike the Pacific Crest Trail from Mexico to Canada. I had my visa approved, gear bought, flight booked, the first stays before the trail arranged, my post re-routed and thousands of other little things taken care of. It's simply not feasible now. 5/6 of the trail go through what are now deemed high risk states California and Washington, and people there are going to have their own problems without me adding to it. Even if I found a way to hike there, I couldn't do so with a good conscience and leave family and friends here in such uncertain times. I thankfully can postpone my sabbatical to next year, but there's always an uncertainty about such massive undertakings. But such things suddenly became far less important. It's about keeping people safe and being there for those who do or might need me right now. Here in Germany, we're hitting exponential growth in numbers (from 157 new infections on Wednesday, to 271 on Thursday, then 802 on Friday and about 1800 yesterday). There will be no way around more restrictions similar to those in the countries around us.
  8. There's already a github issue about this. Perhaps give it an upvote?
  9. WireCache tries to be smart (too smart) when it finds a valid json string because it uses json to serialize array data for storing. So any string that look like json gets json_decode()ed into an array. It's kind of a known bug because there is currently only a part of a fix implemented in WireCache. A workaround can be to prefix your string to break WireCache's json recognition and strip it after retrieval, like this: $response = substr($this->cache->get('mycache', 60, function() { return 'JSON{ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": { "GlossEntry": { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": { "para": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": ["GML", "XML"] }, "GlossSee": "markup" } } } } }'; }), 4);
  10. Not with the built-in anchor select. If you don't mind a bit of regex ugliness: wire()->addHookAfter("ProcessPageEditLink::execute", function(HookEvent $event) { $page = wire('pages')->get((int)wire('input')->get('id')); if(wire('input')->get('href')) { $currentValue = wire('sanitizer')->url(wire('input')->get('href'), array( 'stripQuotes' => false, 'allowIDN' => true, )); } else { $currentValue = ''; } $inp = wire('modules')->get('InputfieldSelect'); $inp->attr('id+name', 'select_anchor'); $inp->label = wire()->_('Select Repeater Anchor'); $inp->icon = 'anchor'; $inp->collapsed = $currentValue ? Inputfield::collapsedNo : Inputfield::collapsedYes; // Instead of addOptions here, fill your select however you want $inp->addOptions([ "" => "", "#some_anchor" => "some_anchor_text", "#other_anchor" => "other_anchor_text", "#third_anchor" => "third_anchor_text" ]); if($currentValue) $inp->attr('value', $currentValue); $wrap = new InputfieldWrapper(); $wrap->append($inp); // It's a bit ugly, but to get our InputfieldSelect to render correctly, we need // it rendered by an InputfieldWrapper. We do that, then strip out the wrapping // parts afterwards (i.e. everything before the first <li> and after the last </li>). $html = $wrap->render(); $html = preg_replace('~^.*?(?=<li\b)~is', '', $html); $html = preg_replace('~</li>.*?$~is', '', $html); $js = '<script> $("#select_anchor").bind("change", function(evt) { $("#link_page_url_input").val($(evt.target).val()).change(); }); </script> '; $html .= $js . "</li>"; $event->return = preg_replace("~(?=<li[^>]+id='wrap_link_page_file')~", $html, $event->return); });
  11. It looks at the HTML in the CKEditor field you're triggering PWLink from, but that shouldn't matter anyway. This is how it should look: The anchor select only appears if there are anchors in the array. What does bd($anchors) say before it's assigned to the input var?
  12. The builtin feature means that PW parses the HTML for named anchors, and if found, adds a "Select Anchor" select box at the top right. Did you remove the if($page->template...) line in my example? This was just meant for demonstration of limiting the functionality to a certain template.
  13. @ryan, I just fiddled with custom Page classes and hit the same issue as @rafaoski. I can access every Page property from methods in my custom class but not createdUser and modifiedUser. <?php namespace ProcessWire; class BasicPagePage extends Page { public function myMethod() { $creator = $this->createdUser; var_dump($creator); // Outputs: // NULL $creator = $this->get('createdUser'); var_dump($creator); // Outputs: // object(ProcessWire\User)#214 (7) { // ["id"]=> // int(41) // ["name"]=> // string(5) "admin" // ["parent"]=> // string(26) "/processwire/access/users/" // ["template"]=> // string(4) "user" // ["email"]=> // string(15) "nobody@invalid" // ["roles"]=> // string(17) "(PageArray) 37|38" // ["data"]=> // array(2) { // ["email"]=> // string(15) "nobody@invalid" // ["roles"]=> // object(ProcessWire\PageArray)#189 (3) { // ... // } } } Calling $page->createdUser->name from outside works, though. Inside the class, $this->createdUser never hits Page::__get().
  14. Not without a hook, but this should work: // Hook for site/ready.php that makes $page->render($fieldname) look for // its template in site/templates/$templatename/fields/$fieldname.php. // Specifying alternative files still works. // Pass a path with a leading slash as $file to go directory from the templates dir. $storedFieldTemplates = []; $this->addHookBefore("Page::renderField", function(HookEvent $event) use($storedFieldTemplates) { $page = $event->object; $file = $event->arguments(1); $storedFieldTemplates[] = $this->config->paths->fieldTemplates; $this->config->paths->fieldTemplates = substr($file, 0, 1) == '/' ? $this->config->paths->templates : $this->config->paths->templates . $page->template->name . "/fields/"; }); $this->addHookAfter("Page::renderField", function(HookEvent $event) use($storedFieldTemplates) { $this->config->paths->fieldTemplates = array_pop($storedFieldTemplates); }); Shortens it down to $article->render('article_lead', 'lead')
  15. Here's a quick and dirty demo how to add your own anchors to the builtin anchor feature of ProcessPageEditLink. No form manipulation shenanigans and no JS either. 😉 wire()->addHookBefore("ProcessPageEditLink::execute", function(HookEvent $event) { $page = wire('pages')->get((int)wire('input')->get('id')); // Limit to a certain template type: if($page->template->name !== 'home') return; $anchors = is_array(wire('input')->get->anchors) ? wire('input')->get->anchors : []; // This is the spot to add your own annotation anchors: $myAnchors = [ "some_anchor", "other_anchor", "third_anchor" ]; $anchors = array_merge($anchors, $myAnchors); wire('input')->get->anchors = $anchors; });
  • Create New...