Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 05/30/2019 in all areas

  1. It's possible, but not as simple as it should be because it seems that the option() method of Datepicker (and Timepicker) is not working for the stepMinute option. Instead it seems you have to destroy and re-init the datepicker if you change stepMinute. In some custom admin JS, for a field named "date"... // For a Datetime field named "date" with time enabled $('#Inputfield_date').on('focus', function() { // Get the existing options for the Datetimepicker var options = $(this).datetimepicker('option', 'all'); // If the picker has the default stepMinute setting... if(options.stepMinute === 1) { // Set custom stepMinute setting options.stepMinute = 15; // Destroy picker $(this).datetimepicker('destroy'); // Re-initialise picker $(this).datetimepicker(options); } });
    4 points
  2. That should work out pretty well... unless I'm missing an important detail here. But... to be very honest... in order to accomplish and maintain such a setup you should be at least an intermediate ProcessWire-user with some kind of experience. These multisite setups – either option 1 or 2 – bring their very own issues with them and you need to be able to handle those and the whole environment (the hosting and server setup) surrounding them. I'd recommend to set up an instance of ProcessWire for each client just to be safe. One mistake and all your clients would be down/see errors/or whatever. You could repackage customizations in modules and distribute those to each client. That's intermediate/advanced stuff as well but way more secure on a larger scale. If you just want to maintain different sites for yourself... play around and have fun.
    3 points
  3. I agree 100% to what @wbmnfktr said! If you want to get rid of repeated task jump into module development and build reusable components that you can share. Far better than putting many sites under one hood. I know what I'm talking about - I've also done that once and regretted it lateron ? Building modules also has the benefit of being more flexible (you don't end up in all sites having the 100% same setup) and last but not least: You can share them with the community ?
    2 points
  4. RepeaterMatrix is going to be the best choice for any type of page builder in ProcessWire (at least at this time). The recent updates to the module improve its flexibility further, such as being able to change the matrix-type of an item that's already been added to a page (this is similar to Gutenberg functionality of being able to change block-types... nice). After using RepeaterMatrix and its equivalents in other CMSes over the years (such as WordPress ACF Flexible Content field), my suggestion is you're better off NOT providing fully customizable layout functionality within your builder (that is, avoid the capability of allowing users to add things like containers, rows, columns). I've personally found that even other CMSes that do this well and are built around that concept are just too clunky. It's the nature of the beast. The better approach in my opinion is to provide a good set (5-10) of matrix-types/blocks that can instead achieve this. Once again, the recent feature addition whereby matrix types can be changed is going to help here since switching a matrix-type retains its content as long as the matrix-type you are switching to uses the same fields.
    2 points
  5. I hadn't looked - thanks for posting that - it's pretty clear from that @todo that Ryan know about this and that it needs fixing. Obviously calling findOne() if it's a selector isn't enough to get it to return NullPage as things currently stand, but this really should be fixed because with the current behavior you can't simply do a normal: if($result->id) on an in memory selector that returns no results because of the null vs NullPage - this has annoyed me for a long time ?
    2 points
  6. Thank you @Robin S, that is exactly what I need! Referring to a field through form in hooks is something I haven't come across yet. It's always exciting to find new things to explore!
    2 points
  7. Here's an example... The page structure: Some pet species have breed child pages and some do not. The selector string for selectable pages for the breed field is "parent=page.species". In ready.php: $wire->addHookAfter('ProcessPageEdit::buildForm', function(HookEvent $event) { /* @var InputfieldForm $form */ $form = $event->return; $breed_field = $form->getChildByName('breed'); if(!$breed_field) return; $species_with_breeds = $event->wire('pages')->find('parent=/selects/pets/, children.count>0'); $breed_field->showIf = 'species=' . $species_with_breeds->implode('|', 'id'); });
    2 points
  8. This is the topic for the new module, TextInputAwesomeplete. Github: https://github.com/outflux3/TextInputAwesomplete Modules Directory: https://modules.processwire.com/modules/text-input-awesomplete/ Text Input Awesomplete Key Points: Uses Awesomplete JS library for instantiating autocomplete suggestions on text input fields in Processwire CMS. Supports any text field, including Page Title (FieldtypePageTitle). Allows admins to configure a list of suggestions (textarea input), or pull suggestions from Processwire pages, by configuring which pages to pull from and which field's value to use. About Awesomplete https://leaverou.github.io/awesomplete/ https://github.com/LeaVerou/awesomplete Benefits & Uses Can be helpful for fields where users may need to enter the same text in the same field on multiple pages, and you can't or don't want to use a Page Reference field. One example could be a site where you send emails using various boilerplate subjects; Another place to use this would be if you had an existing site with a text field that has some inconsistency when same values are added. The autocomplete would help editors to always use the same format as the other pages with the same value. Installation Upload or install from Modules directory. Usage & Configuration Once installed, on any text input field (including Page Title), you will see an option to enable autocomplete. Once enabled you will have the option to type a list of items for autocomplete suggestions, or enable the module to search pages for suggestions. Note that if you enter any items in the Items List field, those will always be part of the autocomplete suggestions, in addition to pages if configured. If you elect to use pages for the suggestions, you have these options: Choose a template to limit by (adds a template=sometemplate to the pages find selector). Override which field to pull suggestions from (by default it will use the field you are configuring). Sets the $field!= in the selector. Setup a Selector for finding the pages for the autocomplete suggestions. This overrides the template selected. Note that the selector needs to return pages that use the field being configured, or the field selected for override. Screenshots: (1) Examples of in-use: Module Configuration Screen
    1 point
  9. this is like gutenberg https://codex.so/editor
    1 point
  10. https://github.com/processwire/processwire-issues/issues/896
    1 point
  11. Either what @bernhard said or your path is wrong. The last is the main thing I'm struggling quite often with. When I get my paths right it works as expected. Even with things from repeater/repeater matrix items.
    1 point
  12. Have you had a look at PageArray.php? And in WireArray.php: Not sure if it should return a NullPage or null/false - but I guess it should be consistent... To add one more: findOne() returns "false" ?
    1 point
  13. Likely _main.php is being appended automatically: https://www.google.com/search?q=site:processwire.com+appendtemplatefile
    1 point
  14. Thanks, that's one way if i can't hook something. It'd be nice to have a default field though.
    1 point
  15. get() should return a NullPage in both cases, if $categories returns a PageArray. Since find() could return a PageArray or an array: what does $categories return?
    1 point
  16. And done – was a simple case of me forgeting I've switched to tag-based releases.
    1 point
  17. Ah, my apologies - will sort this out. ?
    1 point
  18. Hi @dragan, I'm fairly new to ProcessWire forums, so a bit over two months later I finally see your response ? Console didn't show anything suspicious, and neither did ProcessWire error logs. However, some time after scratching my head around this issue I noticed that it solved itself - no idea when, how or why, but every icon is shown correctly now. Hopefully I won't come around this issue again!
    1 point
  19. I had some issues with server provider and subdomain SSL certificate (I want all my sites use forced https), but after those were resolved, @dragan's solution works perfectly! So thanks again, now I'm able to use actual data also in testing phase, which helps in UI design.
    1 point
  20. Thanks @Wanze! I found my solution : wire()->addHookAfter('SeoMaestro::renderMetatags', function($event) { $tags = $event->return; $page = $event->wire('page'); foreach($tags as $key => $value) { if($key == 'image' && $key != '') { $matrix_field = $page->matrix->find('type=immagine_singola')->first(); // immagine_singola is my matrix type $matrix_image = $matrix_field->immagine_articolo->url(); // immagine_articolo is the field inside $tags[$key] = $matrix_image; } } }); I have to refactor something, but for now it's ok. Guys, you rock ?
    1 point
  21. @Mikie The module does not truncate any texts, I can see this as an additional setting on field level. The truncate filter looks good, but the used function to parse the expression of ProcessWire does not support this kind of filters. Would be way easier if this could be left to a template engine ? One solution would be to use a hook to truncate the text when rendering: $wire->addHookAfter('SeoMaestro::renderSeoDataValue', function (HookEvent $event) { $group = $event->arguments(0); $name = $event->arguments(1); $value = $event->arguments(2); if ($group === 'meta' && $name === 'description') { $event->return = substr($value, 0, 200); } }); Cheers
    1 point
  22. @3fingers Did you try if it works? I think it won't because the module currently expects an image field on the page, it cannot resolve nested fields. For text based placeholders, this should work, as the module uses ProcessWire's wirePopulateStringTags function which supports nested WireData objects. One solution would be the one mentioned by @Mikie: To populate the og image URL from your matrix field when saving the page, via hook. Another possibility is to use a hook provided by the module to modify the OG image url when being rendered, check out the following issue and the linked test cases for the hooks: https://github.com/wanze/SeoMaestro/issues/8 Cheers
    1 point
  23. Ok... well... that's kind of easy as well - or it should be at least for you. As you used Bitnami there should be a dedicated Bitname folder somewhere now. C:\Bitnami User>Bitnami Something like that I guess - I'm not sure as I don't use Bitnami. But... within that default Bitnami project (ProcessWire) folder you will find a folder called site and within that a folder called templates. So... it might be C:\Bitnami\Processwire\site\templates
    1 point
  24. if($config->ajax) { header('Content-Type: application/json'); echo $json; $this->halt(); // like die(); } else throw new Wire404Exception();
    1 point
  25. Hi @Autofahrn, thx for that suggestion. I did not try that. But I'm not sure how I should/could do that to get a helpful output? I've found the issue, but would still be interested in a way to show a backtrace of all executed hooks ? I've added a file_put_contents(... FILE_APPEND) to WireHooks::runHooks() to dump all executed hooks to a file called hooks.txt. That could be a first step in the direction that I wish would exist already. The issue in my case was that my CRM module was loaded twice, so all methods added via hooks actually ran twice. I found that by inspecting the debug mode tools, where my cloneInvoice() method showed up twice (and so did all other CRM hook methods). The solution was to make the module "singular" (and do a module refresh). But still I think it would be great to have a chronological list of all executed hooks so that one can instantly see which hook fired when (and after/before what other hooks).
    1 point
  26. @BitPoet Many thanks for this nice helper! Whats about a little enhancement like this? protected function getStyle() { $bgcolor = $this->bgColor; if($this->config->devModeBgColor) $bgcolor = $this->config->devModeBgColor; if(! $bgcolor) $bgcolor = 'rgb(153, 12, 94)'; $fgcolor = $this->fgColor; if($this->config->devModeFgColor) $fgcolor = $this->config->devModeFgColor; if(! $fgcolor) $fgcolor = 'rgb(255, 255, 255)'; $devstring = $this->devString; if($this->config->devModeDevString) $devstring = $this->config->devModeDevString; if(! $devstring) $devstring = 'DEV'; ...
    1 point
  27. Wow, that sounds nice as well! And fairly easy to implement too. You know what they say, work smart, not hard!
    1 point
  28. Another (rather lo-fi) setup could be: Use dev template files, as alternative templates. For testing out new content, you can leave pages unpublished and still preview them when logged in. If your client (role) has permissions to switch templates with Tracy Debugger, there the template switcher panel you could use. https://processwire.com/blog/posts/introducing-tracy-debugger/#template-path-panel https://processwire-recipes.com/recipes/use-different-sets-of-template-files/
    1 point
  29. Hmm, that's a good point. There certainly are some risks that come with having the same database that I haven't considered. Thanks for pointing them out! First solution doesn't work in this case, because client wants to test how things work with adding real content, so they probably wouldn't like the idea of things being wiped with every update. The second option with migrations sounds cool though - might be just what I need!
    1 point
  30. I would concentrate on improving these and the Page Table field. For clients wanting to edit content easily, frontend editing is often enough. Actually, my clients would not be able (or willing) to use a pagebuilder anyway, they just want to click on ONE thing and edit text or images, any more than that and I am asked to do it instead.
    1 point
  31. Longtime WP user. Came here to escape the madness that is Gutenberg. Please, for love of ProcessWire, do not include any such editor crap inside core. People can do so via modules or even admin themes but keep PW clean, neat, tight, free and fresh from such nonsense. Just learned about ProcessWire a couple days ago at a JS workshop/conference. Reading the docs, doing first examples and totally in love with it all. Keep it that way please. Regarding Gutenberg. Not only do you need to know React deeply, no also JS and a lot of it and deeply also, then you get to work with a "the WP way" version of React to build things. With Gutenberg WP has set the bar to entry into the WP world way above average, all the hobby coders that could easily make a WP site given a month of learning are now facing a very steep and intense learning curve. This will surly show going forward. This is what got WP off the ground in the first place. Ease of use and also ease of getting a site done. This has changed. Kids these days want to see results, fast. Sure if you don't care about PageSpeed or WebPageTest, just need a page-builder, plaster external libs all over the source, go ahead, if that is your game, and if that is what you unknowing client pays for, the sure, yes, use WP and Gutenberg exactly for this kind of crap. But if you really do care about all these things and want to make a good site that performs well where the client can have multiple custom blocks showing in the frontend, then you are going to have to invest a lot of time learning JS and React and "the WP way of React". Not something I see any entry level coder feeling up to. For example Just go ahead and make a responsive image block, and I don't mean just the img tag but something more like this. https://dev.opera.com/articles/responsive-images/ Asked around many frequented channels, senior and seasoned devs could not come up with something that produces usable source code. One guy had a solution, asked him if he could show the code "sorry, no, we have a team of devs working on that in our agency and cannot show it publicly". Go figure. A whole team of devs at an agency for a responsive image block to work in WP. Well done Matt and super smooth more there Mark, slipping React into WP that way. A good colleague that has been using WP all his life and knows PHP inside out tells me "I am going to stay away from Gutenberg for as long as I can". By your means, feel free and make a module, load the editor of your choice, give the client what you think they need or want, but do all this strictly kept away from the beautiful, clean and nice source that is ProcessWire. Given the WP mess I am sure there will be more and more people going to use ProcessWire in the future. I plan to speak publicly about ProcessWire at a conf as well as hold workshops, I am that much convinced about it. I would not even go this way if I would have discovered any dependencies on external libs or any such page-builder crap that now WP has built in. And now back to the docs and examples. It is such a pleasure. ProcessWire.
    1 point
  32. Hi @bernhard! Gutenberg in Wordpress is a dual misconception: Wordpress is known as a blog platform. Yes, you can extend it massively and use it for many different projects but in the end it's mostly about operating with text. It's usually enriched with images and embeds but it's still an article, news, etc. So many authors for so many years just copied and pasted their texts, added few media and with 2-3 clicks published it. Now, doing this simple task with Gutenberg is insanely uneffective: instead one simple menu in editor there are several (hidden) menus everywhere (in every block). And EVERYTHING is a block now - a title, a paragraph, an image, a quote and so on (imagine the amount of additional code it generates!). You have to do absurdly much more things to get the same result and you have to spend much more time to do the simplest task. So maybe Gutenberg is for designers rather? If it's true and if this was the idea (to simplify building content) - there are so many so much better WP site builders and themes (to do so) FOR YEARS! Anybody who wants a one-page site or portfolio just picks up a theme and few plugins and voila. The core blogging mechanism stays safe and ready when necessary. I can understand that Matt, Automattic and the dev-deciders want to turn with WP elsewhere and change the character/purpose of the platform. Their choice (though the style they're doing that is embarrassing). But cutting out all those (millions?) of websites using WP for TEXT PUBLISHING and trying to convince the whole world that Gutenberg is better tool to write an article than TinyMCE or CKEditor is as funny as idiotic. From practical point of view, Gutenberg is incompatible with so many plugins and themes (used stably for years!) that it broke hundreds (thousands?) of websites. Blank sites, errors, bugs everywhere AND in many cases people have no idea where is a problem and what to fix. At my site (mentioned above) I have 50 plugins. Half of them doesn't work or generates errors with Gutenberg. Just take a look at the reviews of Gutenberg (and their dates!) to catch the disaster happening there. I know perfectly from my own experience how such a "click click drag-and-drop magic" approach can be tempting. Probably even using PW at some point (it's still ahead of me!). But it's the whole different way and phillosophy of creating (fast) content. There are all those Wix, Weebly, Spacesqare and Mobirise builders for that. WordPress as it was thought in the beginning shoudn't go that way (that 30% of web share will fall quickly).
    1 point
  33. That worked for me! Thanks @Robin S
    1 point
  34. You could do this in admin.php (above the line that brings in controller.php): $wire->addHookAfter('AdminTheme::getExtraMarkup', function($event) { $extras = $event->return; $extras['head'] .= '<link rel="shortcut icon" href="'.wire('config')->urls->templates.'favicon.png">'; $event->return = $extras; });
    1 point
  35. Here are some API additions to the dev branch, primarily for WireArray/PageArray/etc. I've found these very handy lately, and would have on almost any project I worked on, so decided they'd add value to the core. I'll add these to the cheatsheet once 2.4 replaces 2.3, but for now, here they are. The examples here use PageArray, but note that these API additions apply to any WireArray derived type, not just PageArray. WireArray::implode() Implode all elements to a delimiter-separated string containing the given property from each item. Similar to PHP's implode() function. Usage: $string = $items->implode([$delimiter], $property, [$options]); Arguments: $delimiter - The delimiter to separate each item by (or the glue to tie them together). May be omitted if not needed $property - The property to retrieve from each item (i.e. "title"), or a function that returns the value to store. If a function/closure is provided it is given the $item (argument 1) and the $key (argument 2), and it should return the value (string) to use. [$options] - This argument is optional. When used, it's an array with modifiers to the behavior: skipEmpty: Whether empty items should be skipped (default=true) prepend: String to prepend to result. Ignored if result is blank. append: String to prepend to result. Ignored if result is blank. Examples: $items = $pages->find("template=basic-page"); // render all the titles, each separated by a <br>, for each page in $items echo $items->implode('<br>', 'title'); // render an unordered list of each item's title echo "<ul><li>"; echo $items->implode('</li><li>', 'title'); echo "</li></ul>"; // same as above, but using prepend/append options, // this ensures no list generated when $items is empty echo $items->implode('</li><li>', 'title', array( 'prepend' => '<ul><li>', 'append' => '</li></ul>' )); // same as above, but with all items now presented as links // this demonstrates use of $property as a function. note that // we are also omitting the delimiter here as well, since we don't need it echo $items->implode(function($item) { return "<li><a href='$item->url'>$item->title</a></li>"; }, array('prepend' => '<ul>', 'append' => '</ul>')); WireArray::explode() Return a plain array of the requested property from each item. Similar to PHP's explode() function. The returned PHP array uses the same keys as the original WireArray (if that matters). Usage: $array = $items->explode($property); Arguments: $property - The name of the property (string) to have in each array element (i.e. "title"). You may also provide a function/closure here that should return the value to store. When a function/closure is used it receives the $item as the first argument and the $key (if needed) as the second. Examples: // get an array containing the 'title' of each page $array = $items->explode('title'); // get an array containing the id, url and title of each page $array = $items->explode(function($item) { return array( 'id' => $item->id, 'url' => $item->url, 'title' => $item->title ); }); WireArray::data() Store or retrieve an arbitrary/extra data value in this WireArray. This is exactly the same thing that it is jQuery. I've personally found this useful when building search engines: the search engine can store extra meta data of what was searched for as a data() property. Then any other functions receiving the WireArray/PageArray have access to this additional info. For example, the search engine portion of your site could populate an array of summary data about what was searched for, and the render/output code could render it to the user. Usage: // Setting data $items->data('key', 'value'); // Getting data $value = $items->data('key'); // Get array (indexed by key) of all data $values = $items->data(); Arguments: The above usage section explains all that's needed to know about the arguments. The only additional comments I'd make are that 'key' should always be a string, and 'value' can be anything you want it to be. Example: function findSkyscrapers() { $floors = (int) wire('input')->get->floors; $year = (int) wire('input')->get->year; $items = wire('pages')->find("template=skyscraper, floors=$floors, year=$year"); $items->data('summary', array( 'Number of floors' => $floors, 'Year constructed' => $year )); return $items; } // the render function can focus purely on output function renderSkyscrapers($items) { echo "<h2>You searched for:</h2>"; // render the summary of what was searched for foreach($items->data('summary') as $label => $value) { echo "<p>$label: $value</p>"; } echo "<h3>Skyscrapers found:</h3>"; // note use of new implode() function, though a foreach() would be just as well here echo $items->implode(function($item) { return "<p><a href='$item->url'>$item->title</a></p>"; }); } WireArray::and() WireData::and() Return a new copy of the WireArray with the given item(s) appended. Primarily as a syntax convenience for various situations. This is similar to jQuery's add() and andSelf() functions, but I've always felt "add" implied adding something to the original rather than creating a new combination, so went with "and" in this case. The term "and" is actually a reserved word in PHP, so you can't usually have a function named "and()", but through the magic of hooks, ProcessWire can. This function should reduce the instances in which you'd need to do "$a = new PageArray();" for example. Usage: // create a new WireArray with $items and $item (appended) $myItems = $items->and($item); // create a new WireArray with $items and $moreItems (appended) $myItems = $items->and($moreItems); // create a new WireArray with $items and $item (prepended) $myItems = $item->and($items); // create a new WireArray with $item and $anotherItem (appended) $myItems = $item->and($anotherItem); // create a new WireArray 4 items $family = $pappa->and($mamma)->and($brother)->and($sister); Examples: // generate breadcrumb trail that includes current page foreach($page->parents->and($page) as $item) { echo "<a href='$item->url'>$item->title</a> / "; } // check if page or its children has a featured checkbox if($page->and($page->children)->has("featured=1")) { echo "<p>Featured!</p>"; }
    1 point
  36. He did it again Thanks Ryan, I can see me using these a lot! There were many times when I wished that some of these methods would exist.
    1 point
  37. Well deleting the original will leave you with a problem as you already know It would be relatively easy to script a batch resize all original images and run that once over all page that has images. Use the ImageSizer class. Working example: $pa = $pages->find("template=basic-page,images.count>0"); foreach($pa as $p){ foreach($p->images as $i){ $ImageSizer = new ImageSizer($i->filename); $ImageSizer->resize(120,0); } } It will resize all the original images to 120x*. And you're done. (This particular example show how cool the on-page images are.)
    1 point
×
×
  • Create New...