Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/24/2018 in all areas

  1. This week we look at ProcessWire’s strategy of continuous improvement and refactoring on top of our solid foundation, and in ProcessWire 3.0.111 that brought refactoring to a few core classes and some other useful additions… https://processwire.com/blog/posts/pw-3.0.111/
    6 points
  2. Just had a small world experience. I have been emailing with Ueli at https://www.whatwedo.ch/ who are the folks who operate the https://ip.nf/ IP to country API service. He just mentioned that they are partners with https://novu.ch/ (built with PW) and that they use ProcessWire a lot. So anyway, he is keen to support this module and to make sure their service will be able to keep up with any requests made by it to their service ?
    5 points
  3. Just committed a significant upgrade. The IP to country lookup now has three services it can use - all of which support IPV6. You can specify the order and remove some if you like. They will be used in order and in case one fails, it will move onto the next one. You can now specify an IP address in the config settings to test. Note that saving the module config settings will remove the "FromEU" session variable so the result will be fresh each time. Also, because all of these three services can automatically detect the user's IP address, I am no longer supplying it via the API call (unless you are using the test option), which means that tests from your localhost dev environment will actually work properly. I have also included Tracy bd() calls that return more information. Obviously this will only show if you have Tracy installed, but it tells you which service was used, the results from it, and then the call to the other service to check if the country is in the EU, as well as the result of this test: true/false.
    3 points
  4. The tree selection is probably not possible without some serious coding. You can get a long way though by using what's already built into PW. I'd do it like this: Create your repeater field (lets call it "quotes") with the field for the quote text (I'll call it "quote") and add it to a template Create pages with that template and add a few quotes Add a field of type "Page Reference" (let's call it "quotelink"), set it to "Single Page or Null Page" On the Input tab for that field, select "Custom format (multiple fields) ..." in the "Label field" box, and in the "Custom page label format" input enter "{custlabel}" (we will fill that virtual property later) Expand the "Custom PHP Code" option in the "Selectable pages" section, copy the code there to site/ready.php and adapt it to walk through the persons and add all quote repeater items to the output. In that code, populate the "custlabel" property for each repeater item so the displayed text makes sense (e.g. by prefixing the first 80 characters of the quote with the person's name). Here's an example: <?php $wire->addHookAfter('InputfieldPage::getSelectablePages', function($event) { if($event->object->hasField == 'quotes') { $out = new PageArray(); $persons = $event->pages->find('template=person'); foreach($persons as $person) { foreach($person->quotes as $quoteitem) { $quoteitem->custlabel = $person->fullname . ": " . substr($quoteitem->quote, 0, 80); $out->add($quoteitem); } } $event->return = $out; } }); Add the quotelink field to a template Now you should be able to add a page with that template and select an arbitrary quote in your quotelink field In your template code, output $page->quotelink->quote
    3 points
  5. The Page List Select (InputfieldPageListSelect) is rather specific and can't deal with a flat list of pages, that's why the code option is disabled there. I don't think there's a way to extend it to do what you want. To implement something similar, you'll need to write your own Inputfield implementation (and perhaps even extend InputfieldPage itself), that's what I meant above with "serious coding". You'd need to write both the PHP module code and the JS that does AJAX pagination and tree expansion, so it's not something done in an hour.
    2 points
  6. Looks like extreme-ip-lookup.com can't deal with IPv6 address. And PW is on the same boat.
    2 points
  7. Maybe there should be a note in the plugin settings that using Checking EU is sending personal IP data to extreme-ip-lookup.com (USA?) and restcountries.eu which might be breaking GDPR law (Server location?), when checking that option. [OFFTOPIC] Tracy: I only use parts of it, especially using bd() causes an Uncaught Error: Call to undefined function bd - had no time to figure that out yet [/OFFTOPIC] ... your question replied the quick 'n dirty way: echo "|" . ($this->get_user_ip_addr()) . "|"; returns |::1| The notice only appears when first visiting the page, it is gone after a refresh and visiting other pages of that site. (PHP 7.1) My solution for now: Unchecking the EU feature.
    2 points
  8. The editor should be "namespaced". Are you able to provide a screenshot of the conflict (with inspect element on the issue).
    2 points
  9. This is much easier ? $u = $users->add('user-name');
    2 points
  10. When "Use HTML Purifier" is enabled for a CKEditor field any data-* attributes are stripped out. This happens regardless of the CKEditor ACF settings, and is pretty annoying considering how frequently data attributes are used/needed these days. I'd like to keep HTML Purifier activated but I want to change the configuration to allow specific data attributes. I know how to do this via addAttribute() - as mentioned here - and I can get this working if I directly edit MarkupHTMLPurifier::init() and clear the HTML Purifier cached files from /site/assets/cache/. public function init() { $this->settings->set('Cache.SerializerPath', $this->getCachePath()); $this->settings->set('Attr.AllowedRel', array('nofollow')); $this->settings->set('HTML.DefinitionID', 'html5-definitions'); $this->settings->set('HTML.DefinitionRev', 1); if($def = $this->settings->maybeGetRawHTMLDefinition()) { $def->addElement('figure', 'Block', 'Optional: (figcaption, Flow) | (Flow, figcaption) | Flow', 'Common'); $def->addElement('figcaption', 'Inline', 'Flow', 'Common'); // Added line below to allow data-ext attribute on 'a' elements $def->addAttribute('a', 'data-ext', 'Text'); } } But how can I change the configuration like this without modifying a core file? I want to set the configuration from a custom module. I don't see any hookable methods in MarkupHTMLPurifier but surely it must be configurable somehow. Does anyone know a way to do this?
    1 point
  11. MarkInPageTree New module which does what it says in the title. It adds an icon to a page on the page tree if -> a specific field is true and / or is a specified template. For example I'm using it to add an icon to any page that has a checked (checkbox) exclusive field. This helps with admin clarity as you can see instantly which pages of the same template have differing content (i.e. are exclusive or not). https://github.com/benbyford/MarkInPageTree
    1 point
  12. Hello for all, ConfigurationForm fieldtype module is one my experiment from 2016. Main target to build this module was to store multiple setup and configuration values in just 1 field and avoid to use 1 db table to store just single "number of items on page", or another db table to store "layout type" etc. Thanks to JSON formatted storage this module can help you to reduce number of PW native fields in project, save DB space, and reduce number of queries at front-end. Install and setup: Download (at the bottom ), unzip and install like any other PW module (site/modules/...). Create some filed using this type of field (ConfigurationForm Fieldtype) Go to field setup Input tab and drag some subfields to container area (demo). Set "Name" and other params for subfields Save and place field to templates ("Action tab") How to use it: In my case, I use it to store setup and configurations values, but also for contact details, small content blocks... (eg. "widgets"). Basic usage example: ConfigForm fieldtype "setup" has subfields: "limit", type select, option values: 5, 10, 15, 20 "sort", type select, option values: "-date", "date", "-sort", "sort" // get page children (items) $limit = isset($page->setup->limit) ? $page->setup->limit : 10; $sort = isset($page->setup->sort) ? $page->setup->sort : '-sort'; $items = $page->children("limit=$limit, sort=$sort"); Screenshots: Notes: Provide option to search inside subfields Provide multilanguage inputs for text and textarea field types Provide option for different field layout per-template basis Do not place/use field type "Button" or "File input" because it won't works. Please read README file for more details and examples Module use JSON format to store values. Text and textarea field types are multilanguage compatible, but please note that main target for this module was to store setup values and small content blocks and save DB space. Search part inside JSON is still a relatively new in MySQL (>=5.77) and that's on you how and for what to use this module. Thanks: Initial point for this fieldtype was jQuery plugin FormBuiled and thanks to Kevin Chappel for this plugin. In field type "link" I use javascript part from @marcostoll module and thanks to him for that part. Download: FieldtypeConfigForm.zip Edit: 14. August 2018. please delete/uninstall previously downloaded zip Regards.
    1 point
  13. So, food for thought in terms of REGEX vs DOMDocument: Benefits of using REGEX: Essentially faster/more efficient for processing of the data Doesn't care about valid source structure as it's parsing straight text, not XML nodes Implementation is unlikely to change Detriments of REGEX: Writing a perfect implementation of a REGEX when dealing with HTML to handle all use-cases without experiencing any edge-cases is difficult (might "greedily" match more than intended) It definitely works, but the developer argument is: is it the best (most appropriate) tool for the job? Without a good knowledge of REGEX, harder to understand the underlying code if changes/updates are required Benefits of using DOMDocument: Written specifically for the purposes of this type of task (searching/modifying the DOM) DOMDocument shouldn't ever be "greedy" over what it matches, like REGEX unintentionally tends to do Detriments of DOMDocument: May require valid HTML, but with iterations of HTML, what exactly is considered valid? Would different versions of PHP handle the DOM differently with version differences? Potential of implementation changes. loadHTML() may modify your source - what goes in might not be what comes out Character encodings may cause unforeseen issues (don't they always!) Without a good knowledge of PHP's approach to using DOMDocument, the code process can get rather difficult to understand if changes/updates are required Some further reading from someone else with more thorough testing: https://blog.futtta.be/2014/05/01/php-html-parsing-performance-shootout-regex-vs-dom/ https://blog.futtta.be/2014/04/17/some-html-dom-parsing-gotchas-in-phps-domdocument/ Realistically it's a judgment call. Speed and server efficiency versus (one would hope) better valid modifications/detections. I don't think there's really a right or wrong solution. Some shared hosting servers don't install the DOMDocument PHP extension by default though, so you'd want to check for the existence of the function during your module's install method. P.S. - Thanks for asking the question -- I knew DOMDocument was slower, but haven't compared in awhile. The articles I saw above were an interesting read. ?
    1 point
  14. Why not just use the Page reference Autocomplete?
    1 point
  15. I don't quite fully understand the scenario, but maybe you could use the inputfield selector. As a default selector you could point to the repeater parent (under Admin), and then go from there? Or maybe try the Connect Page Fields module; perhaps it'll simplify the cross-referencing https://modules.processwire.com/modules/connect-page-fields/
    1 point
  16. Yeah, looks like you are correct. I have found another free service that support IPv6 and it seems to be working fine now. I have committed a new version with this - I'd appreciate if some others could test and make sure there are no issues at your end. Note these lines: https://github.com/adrianbj/CookieManagementBanner/blob/609617167e476fb5a2d964aa431e2a8e7a749a93/CookieManagementBanner.module#L48-L50 if you want to force an EU IP address for testing - both the IPv4 and IPv6 addresses are German. Interesting point - I don't honestly know the ins and outs of the law, but I have added a note mentioning this to the config setting. A way to partially avoid this is relying on a local IP to Country database, but they are a pain to maintain, so I think for now the warning will have to do and devs can decide what they prefer. OT, but has anyone out there tested the vanilla JS fork by tpr yet? @GhostRider ?
    1 point
  17. @gebeer It was a great post. Just one addition to what you have written. In case someone has a multilingual website the route to api will become => http://mywebsite.com/en/api/pages/. Notice the addition of language key here (en).
    1 point
  18. Nice work @joer80! It's great to see how others approach their own page builders. Hopefully we can all learn better ways of building out our own page builders. I've taken a slightly different route and have used repeater matrix fields to build out the page layout/sections, whereas you have used pages. I like how yours integrates the structure and content into the flow of the page tree. I originally thought about this, but had concerns of content & layouts that I wanted to repurpose for some/all pages. I know it would be easy to copy a page and it's children to another parent, but I thought it would be easier to use a selector field to select where I wanted to place these. How do you approach this? Do you have any difficulty with this? The other reason I went this approach was I could easily lock down the template section and users could still change the current content and all of the widget options that I make available. The downside with my approach was it got a bit messy once the site started to grow. I recently had to change mine up a bit due to this. I originally had just a parent page 'templates' and 'widgets' but soon got out of control. I now have the same parents pages, but now seperate child pages into groups. I'm still looking to improve on this which I hope I can refine it the more I use it. I also changed the widgets parent page to store all widgets that are on multiple pages and singular widgets page to sit under the pages or parent pages which they are used for, which sit at the top of the page tree. Thank you @tpr for implementing the sticky page feature in AdminOnSteroids! ? I also improved the way I could target classes, buy separating my css files. Ones that target the page ID, the page name and the widget name as a class. I think I will try and extend this as you have done through a backend-end editor for these files. One thing I would love to find out is a way to automatically update all the uikit classes from an external source. So that whenever anything is changed and updated, new classes would be added. Or have a development section in the page template to test new classes with... etc, so not to break anything. But great stuff, well done! ? Just shows you what can be built using this awesome CMS. ?
    1 point
  19. I think Migrator would need to be updated to support these - it might not be too hard because of the similarity to repeaters.
    1 point
  20. Actually it would be pretty easy, just add .tracy-collapsed { display: block; }. You can even do it without Js by adding a hidden checkbox somewhere above all containers and use something like this: input:checked ~ [selector for an element in the same level] .tracy-collapsed { display: block; } Plus you can wrap the input in a label and format that it as an icon. Update: wrapping the input in a label won't work (the CSS sibling combinator "~" cannot target the desired element), but adding a "for" and an "id" to the label and the input is OK. However, in this case the CSS solution is not applicable because once all nodes are expanded you can't manually collapse individual nodes.
    1 point
  21. Hi @adrian, What do you think about adding a "Expand/Collapse All" button for dumps? This button would expand/collapse all nested elements within a dump would be useful in situations where you are dumping a massive nested object and you want to use the browser's find tool to look for a specific string of text.
    1 point
  22. @thetuningspoon, it would be helpful if you could provide a limited test case (i.e. a minimal setup where this performance problem occurs), or if that's not possible/feasible, a description of the structure and this particular feature in as much detail as possible. For an example: What's the page structure like, and which part of it is cloned? Are users actual users or do you have "user" pages in a custom page structure – and if, do each of these have multiple orders? Or are you linking users to orders via a Page field or something along those lines? How many fields do your orders (if order pages is what you are cloning) have? How many Repeater fields there are, and approximately how many Repeater items (real content or ready items) do they contain? How many users/orders are you dealing with? Where in your page structure are you storing cloned orders? Are there any third party modules (or modules/hooks you've created) that could affect this? As you can see, this raises quite a few questions, and that's just the tip of the iceberg I'm afraid. All in all this sounds like something that would be easiest to debug by setting up a test case – otherwise it's difficult to isolate the issue. As @LostKobrakai already pointed out, 20 seconds for cloning a relatively small page structure is not normal, unless there's a massive amount of data to copy (in db or on disk). If you're dealing with a large number of items, Repeaters could of course also play a role in this: after all each repeater item is a Page, and their storage method can also result in bottlenecks at large enough scale ?
    1 point
  23. a simple way of caching (nearly) everything using wirecache and 2 page render hooks in site/ready.php // the next ensures that the following code will only run on front end (otherwise back end would get cached, too which results in problems) // make sure to place anything you need in the backend before this line or change it to your needs.. if ((strpos($page->url, wire('config')->urls->admin) !== false) || ($page->id && $page->is('parent|has_parent=2'))) return; $cacheName = "prefix__$page->id-$page->template-{$user->language->name}"; if ($urlSegment1) $cacheName .= "-$urlSegment1"; if ($urlSegment2) $cacheName .= "-$urlSegment2"; if ($urlSegment3) $cacheName .= "-$urlSegment3"; if ($input->pageNum > 1) $cacheName .= "-page$input->pageNum"; // if already cached exit here printing cached content (only 1 db query) $wire->addHookBefore('Page::render', function() use($cache, $cacheName) { $cached = $cache->get($cacheName); if ($cached) { exit($cached); } }); // not cached so far, continue as usual but save generated content to cache $wire->addHookAfter('Page::render', function($event) use($cache, $cacheName) { $cached = $cache->get($cacheName); if (!$cached) { $cache->save($cacheName, $event->return); } unset($cached); }); of course not the same as a proper flat file cache like procache but at least saving many database queries make sure to adjust the $cacheName as needed, you can even cache query strings, almost everything you'd like and you could wrap everything in a condition to only run if no incoming post or query strings so form submits keep working example if (!count($input->get) && !count($input->post) && !$config->ajax) { // cache logic from above } have fun
    1 point
×
×
  • Create New...