Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 02/06/2021 in all areas

  1. This week ProcessWire gained powerful new tools for finding pages and controlling how they are loaded. If you like to maximize performance and efficiency, you’ll like what 3.0.172 brings— https://processwire.com/blog/posts/find-faster-and-more-efficiently/
    5 points
  2. @adrian Sounds like a good idea to me. I think it would be possible if your selector specifies which template(s) are in use, so it knows what fields it can autojoin, rather than attempting to autojoin all fields in the system. I can look into it further. Though should also mention that not all fields support autojoin, so it wouldn't technically be possible to autojoin "all", though it could accomplish it by using autojoin to load what it can and then manually load the rest, so it could still deliver pages to you with all of the fields populated and no further loading necessary. Not sure if this applies to your case or not, but wanted to mention that if doing this for just the current/page being rendered, then it wouldn't be worthwhile. The efficiency benefits in autojoin come into play when lots of pages are being loaded. @Zeka It's a similar option in terms of what it does, but also quite different. The new "field=..." option (or findJoin method) uses an entirely different page finding method that performs the find and load in the same query. (This is possible since you are specifically telling it what fields to join). Whereas the options.loadOptions.joinFields you mentioned is just an option to the pages.getById() method that occurs after the find() has already taken place, and it's really more intended as an internal option rather than a public API one. The newly added feature can do the same thing more efficiently, and easily enough that I thought it belonged in the public API. One other difference to mention is that the options.loadOptions.joinFields adds to the default autojoin fields for the loaded pages rather than overrides it. So it doesn't give you the level of control that the new option does unless you don't have any fields with the autojoin flag in your system. No changes here. There's only so much that can be joined in one query per field, so autojoin is not always possible, especially on multi-value (FieldtypeMulti) fields with lots of values. It should be possible on most Page reference and options fields though, so long as they don't have huge amounts of selections. If there's need for it though, I may be able to have fields (where applicable) store a cache of data (like FieldtypeCombo does) that can be autojoined. Since you specified a field that does not exist, I think you are seeing the "no fields specified: load all" behavior here. Probably it would be better if it threw an Exception or just returned a blank result set. Autojoin isn't very useful for the current page, like the one you are rendering. There isn't likely going to be a worthwhile difference in overhead between autojoin fields and load-on-demand fields when rendering the current page being viewed. The difference becomes worthwhile when working with lots of pages that all have the same field. For instance, think of the page-list in the admin—having the title field autojoin is useful there. For most people, they probably don't ever even need to think about autojoin. But for those of us interested in optimization, it does offer some worthwhile improvements in the right situations. I wouldn't bother with trying to autojoin your SEO fields since you would only use those rendering the page being viewed. This kind of micro-optimization can take up your time without delivering benefits you'll ever feel. Though if you wanted to load them all in one chunk, a Combo field would be a great way to do that.
    3 points
  3. Ok this one is mindblowing, looks like a perfect upgrade from the solution I'm currently using. I'm getting by with a repeater and a modded version of FieldtypeSelectFile that basically lets you select a php from a given content blocks directory, assumes there's a png that goes with it, and renders a neat block selector. From there, it's just hiding and showing fields depending on the value of that selector. It's not the most elegant of solutions from the "setting up" perspective, but quite nice and comprehensive for the editor and the php code on the frontend super understandable. Brad seems to try to do just enough. Looks great for custom, controlled content blocks. Too much freedom and the editor usually makes a mess ?
    3 points
  4. In that case it would have to use the existing find() method, which does that: performs a find() to find the page IDs and template IDs, breaks them into different groups by template, and then performs query(ies) to then load the pages with the appropriate autojoin fields for the templates. The new find method used by findJoin() and "field=..." option is a lot simpler so it does all of it in 1 query, which is possible because you are specifying the fields to autojoin (rather than the template, so it doesn't need to figure that part out). I don't yet know if there is a downside, as I've never tried to autojoin-all before. I'm going to look into it though. But I think there are potential downsides, as 1 big query with a lot of joins can sometimes be slower and harder for MySQL to cache than a lot of simple queries. MySQL also has limits on how many joins it can perform in a query and how much data can be concatenated from a multi-row table, so it's likely that autojoin of all fields might be less reliable in some cases. I guess I see autojoin as a good optimization for some (or many) cases where it's found to be reliable and increase performance, but not all cases, and not something to use by default.
    2 points
  5. @ryan - this sounds like another awesome update! Admittedly I haven't played with this new version yet, but my initial thought after reading the blog post is whether we could have a: $pages->find("$selector, field=all"); as a complement to: $pages->find("$selector, field=none"); For many pages/templates, I always need to access all fields on every load and this would make it much simpler than listing out all the fields separately. Does that sound like a useful addition?
    2 points
  6. Hello, I would like to present you a new module which aim to facilitate the productivity of your editors/publishers when working on ProcessWire. The idea begun when my co-worker told me that when typing in ProcessWire CkEditor field he was feeling "loosing motivation" when writing big wall of text and/or inspiration. So he opened his web-browser and show me a site looking to Wordpress - feel free to put your preferred emoji here - then he opened Gutenberg... typed some text and moving some "blocks". I understood immediately why he got this feeling with CkEditor. If you or your client feel like this guy, then you will love this module ! What is currently supported ? Features Auto-save Medias upload support HannaCode support Blocks Implemented Heading Image Paragraph Embed Quote Code Link Table (beta) Block Delimiter Raw HTML Note (custom block markup) Feature Request Frontend Edition And there you go for the preview - sorry I am to lazy and bad at typing text so I had a copy/pasta moment : Module featured in the ProcessWire Weekly #317 - Thanks @teppo
    1 point
  7. Here is the first very early concept of a Page Builder. As per the conversation in the 'ProcessWire beyond 2021' conversation, I set myself a challenge to make a clone of YOOtheme Pro's Page Builder. This was mainly spurred by @Jonathan Lahijani's excellent overview of ideas of a page builder for ProcessWire. This is still in very early stages and I am not really sure where it is headed. I would like to hear the thoughts of like-minded persons ?. I would especially love to hear from @Jonathan Lahijani, @szabesz, @AndZyk and @flydev ?? please. Concept The page builder in its current state is a Fieldtype + Inputfield supported by other behind-the-scenes Fieldtypes without Inputfields. There are no hidden or extra pages in contrast to Repeater Matrix. All values are stored in the Page Builder fields for the page being edited. The fields do not store values as JSON. Definitions for elements, rows, grids, etc as stored as JSON. Currently, for storage purposes, 4 datatypes are supported - Text (HTML), images, plain text and headlines. From a storage perspective, the latter two are one and the same. Just texts with different 'schemas/definitions'. More on this below. The fields are multitype fields. This means one page can hold multiple texts, allowing for repeatability. Similar datatypes are stored together in one field/table. For instance, there is no reason why a (future) URL element (datatype) should not be stored in the same table as plain text. At the database level, they are both just texts with similar requirements. At the processing level, URLs vs other plain texts (headlines, etc) are handled differently (validation, sanitisation, etc). Each 'element' represents a row in a table for most types (e.g. slideshows are slightly different). Querying and access of field values is via the main Fieldtype - FieldtypePageBuilder. However, the supporting Fieldtypes can be also be accessed and queried individually, if one wishes, using normal ProcessWire selectors. The supporting Fieldtypes, if such need arises could easily become custom tables instead (but best to keep them as Fieldtypes - easier querying with selectors, etc). It is totally CSS-agnostic in relation to frontend output. You bring your own CSS. In the preview, you can also use your own CSS. In the frontend, you can choose to output raw values as you wish or use inbuilt render methods to render the whole layout for you or to render the value of an element as per its tag definition (e.g. headlines as h2, h4, etc) where applicable. Fully multilingual (although the editing UI not yet implemented). Issues The main issue is the real estate needed for InputfieldPageBuilder. Any such page builder would require the whole width of the window. As you can see from the screenshot below, this obviously throws things out of kilter with respect to the ProcessWire page edit UI, in any theme (I believe). I am not a designer so would love to hear from you about possible solutions. My current thoughts are: Modal Open the page builder in a modal for editing. Pros Would allow for use of whole real estate. Title and other fields would not be in the way. Cons Editing in modals can be tricky? Other..? Process Module Pros Solves the real estate issue. Cons Disconnect between the page being edited/created and the page tree. Screenshot No attempt has been made to theme it as per any current ProcessWire theme (that I know of). This was a quick and dirty-ish clone of YTPB. As stated, however, the current ui is not acceptable as an Inputfield for, mainly, real estate reasons. Video Demo This is a demo for the Page Builder app outside ProcessWire. Thoughts? Thanks. PS: I currently have no time to continue working on this (Padloper, etc..)
    1 point
  8. This week we have a couple of useful new $pages API methods. They are methods I've been meaning to add for awhile but hadn't found the right time. The need coincided with client work this week, so it seemed like a good time to go ahead and add them. I'm doing a lot of import-related work and needed some simple methods that let me work with more page data than I could usually fit in memory, and these methods make that possible. These won't be useful to everyone all the time, but they will be useful in specific cases. The first is $pages->findRaw() which works just like the $pages->find() method except that it returns the raw data from the matching pages, and lets you specify which specific fields you want to get from them. For more details see the findRaw() documentation page. There's also getRaw() method which is identical to findRaw() except that it returns the raw data for just 1 page, and like get(), it has no default exclusions. The next method is $pages->getFresh(). This works just like $pages->get() except that it gets a fresh copy of the page from the database, bypassing all caches, and likewise never itself getting cached. ProcessWire is pretty aggressive about not having to reload the same page more than once, so this method effectively enables you to bypass that for cases where it might be needed. Again, probably not something you need every day, but really useful for when you do. More details on the getFresh() documentation page. I'm going to likely cover these new $pages API methods in more detail in a future blog post, along with some better examples, so stay tuned for that. I noticed there's some pretty great conversion and examples happening in the posts on page builders here, but have been so busy this week I haven't had a chance to dive in, but I'm really looking forward to doing so. Thanks and I hope you all have a great weekend!
    1 point
  9. Yes, I assumed it would check the template of each page to be returned and only autoload those relevant fields. Right, but there wouldn't be any downside either, would there? It's a good point of course. I suppose the autojoin would be more useful for example on a blog parent page (showing featured image, title, author, tags, date, summary etc) for the latest 10 posts, rather than an individual blog page showing all those fields plus the full body content.
    1 point
  10. I thought so as well for quite some time, but I also had several problems related to AOS and wasted too much time for debugging just to find out, that AOS was the reason... That's why I don't use it any more and I was surprised - I don't really miss it ? It's nice in many ways, but it's not essential imho and I personally don't want to take the risk of getting too used to a module that does not seem to be maintained any more and potentially brings in too many problems. No AOS bashing here - just trying to support his concern ? I'd much more prefer to get some of AOS features into the core...
    1 point
  11. For advanced needs there is a module from @Robin S : https://processwire.com/talk/topic/21153-access-by-query-string/ But if you need something really quick and simple, just put that in your init.php: if($input->get('code', 'string') === 'YOURSECRET') { // remove the unpublished state in memory (non-persistant) $pages->get('/yourpage')->removeStatus('unpublished'); } This makes /yourpage accessible via /yourpage/?code=YOURSECRET ? PS: I had this need today to show a page to a user that has no login and to make sure that the page is also excluded from search results (that's why just hiding the page would not have been enough).
    1 point
  12. What about this? ? if(!$user->isLoggedin() AND $page->template == 'sometemplate' AND $input->get('code', 'string') == $page->page_pass) { $page->removeStatus('unpublished'); }
    1 point
  13. I figured out a way to do this ( @bernhard's original request, solution #3), but it wasn't easy. I added a page-edit-edit-fields permission which can be added or revoked per-template, and without which none of the fields are editable in the page editor. It required 3 hooks to make the permission work. /site/ready.php /** * Implements a custom page-edit-edit-fields permission. By default, all fields will be view only when the page-edit permission is granted. Adding the page-edit-edit-fields permission makes all fields on the page editable. * This could be accomplished by implementing access settings on every field of the template, but this makes it much easier. * * Individual field access settings, if enabled, will override this feature. * * Both this hook and the one below are required to make this work. */ $this->wire()->addHookAfter('Field::editable', 'fieldEditableHook'); function fieldEditableHook(HookEvent $event) { $return = $event->return; $page = $event->arguments(0); $user = $event->arguments(1); $field = $event->object; if($return === true && $page !== null) { // No need to check our page-edit-edit-fields permission if the field is already not editable or we're not checking page context if(!$user) $user = $event->wire('user'); // If no user passed in, use the current user // If the current user does not have page-edit-edit-fields permission, disable edit if(!$user->hasPermission('page-edit-edit-fields', $page)) { $return = false; } } $event->return = $return; } $this->wire()->addHookAfter('Field::viewable', 'fieldViewableHook'); function fieldViewableHook(HookEvent $event) { $return = $event->return; $page = $event->arguments(0); $user = $event->arguments(1); $field = $event->object; if($return === false && $page !== null) { // No need to check our page-edit-edit-fields permission if the field is already viewable if(!$user) $user = $event->wire('user'); // If no user passed in, use the current user // If the current user does not have page-edit-edit-fields permission, enable viewable permission if(!$user->hasPermission('page-edit-edit-fields', $page)) { $return = true; } } $event->return = $return; } $this->wire()->addHookBefore('Field::getInputfield', function(HookEvent $event) { // Exclude any field types we don't want to make uneditable by default $excludedFieldtypes = [ 'FieldtypeLeafletMapMarker', ]; $field = $event->object; $page = $event->arguments(0); $user = $event->wire('user'); if(in_array($field->type, $excludedFieldtypes)) return; // If the current user does not have page-edit-edit-fields permission, disable edit regardless of the field's roles if(!$field->useRoles && !$user->hasPermission('page-edit-edit-fields', $page)) { $field->set('useRoles', true); //$field->addFlag(Field::flagAccess); // May not be necessary //$field->addFlag(Field::flagAccessAPI); // May not be necessary $field->addFlag(Field::flagAccessEditor); } });
    1 point
  14. Hi @ryan and thank you for such great and in my case in-time update. A couple of questions: Do these codes do the same thing or they differ internally? $items = $pages->find("title|body*=$q, field=title|summary"); and $items = $pages->find("title|body*=$q, [ 'loadOptions' => [ 'joinFields' => [ 'title', 'summary' ] ] ]"); ---------------------------------- I remember that there were some issues with autojoining of multi-value fields with 'loadOptions' option in find method (like page reference or options fields etc). Are there any changes? ---------------------------------- I have found that if I specify a field that does not exist "findRaw" method starts to join default page properties: And without ---------------------------------- What is the right way to handle the situation when we need to autojoin some fields only for the current page. For example, SEO fields in most cases used only on the page object of the current page, but if I set these fields autojoin then than they will be autojoined on every find call, so then we have to specify that we don't want to join these fields in 'joinField' options or via newly added options that also is not very handy. I was trying to set autojoin flag for these field in init.php and remove it in ready.php like // init.php fields('seo_title')->addFlag(Field::flagAutojoin); fields('seo_description')->addFlag(Field::flagAutojoin); fields('seo_og_title')->addFlag(Field::flagAutojoin); fields('seo_og_description')->addFlag(Field::flagAutojoin); //ready.php fields('seo_title')->removeFlag(Field::flagAutojoin); fields('seo_description')->removeFlag(Field::flagAutojoin); fields('seo_og_title')->removeFlag(Field::flagAutojoin); fields('seo_og_description')->removeFlag(Field::flagAutojoin); But in this case, there is no way to check does current template have these fields as on the "init" state template and page variables are not available, so all templates have to have these fields or we will get an error. Maybe there is something already that can help?
    1 point
  15. The Bard field in Statamic has been been discussed and mentioned several times in the forums, dating all the way back to 2018, as something worth emulating in ProcessWire. Here is a short demo of a proof of concept of an unimaginatively (temporarily?) named (and very colourful) module doing just that. Demo App running outside ProcessWire. Screenshot Screenshot of the app in InputfieldBrad, running in a modal, quirks and all. Way Forward I don't know but no current plans for any sort of release, paid or otherwise. I like where @flydev ?? is headed with FieldtypeEditorJs so let's support that ?.
    1 point
  16. Do you mean that editors are pasting absolute internal links into the link dialog in CKEditor? If so you could try an education approach first, i.e. "Please create internal links via the fields in the link dialog". That way you won't get absolute internal links in the first place. Beyond that you could use a saveReady hook to do a string replacement in the relevant field(s): $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); // Perhaps limit by template as needed if($page->template == 'basic-page') { // Internal links: replace absolute href with relative href $page->body = str_replace('href="https://www.domain.com/', 'href="/', $page->body); } });
    1 point
  17. Nice tip!! To elaborate on other examples, I do something like this to have this same "code to view" per page (in the sense of one code per page) like this on ready.php: if(!$user->isLoggedIn()){ wire()->addHookAfter('Page(template=sometemplate)::viewable', function($event){ $page = $event->object; $pass = wire('input')->get->text('pass'); if($page->page_pass && $pass){ if($page->isUnpublished() && $pass == $page->page_pass){ $event->return = true; } } }); }
    1 point
  18. Your code processes both the song_files and img_files uploads, but only adds the song_files to the newly created page. This part of your code adds the song_files upload to the files field of the new page: foreach($files as $filename) { $filepath = $upload_path . '/' . $filename; $newPage->files->add($filepath); $newPage->message("Add file : $filename"); unlink($filepath); } You need something similiar to add the uploaded $images to the page. As a sidenote, duplicating code like this is not ideal. It increases the verbosity of your code and thereby makes it harder to spot errors like this one. See how the sections of your code processing $newImage and $newFile are almost identical? A better approach than duplicating that code would be to write one or two reusable functions that perform the necessary steps (processing the uploaded file as a WireUpload and adding it to the page). You can use function arguments to express the differences between the two uploads (name of the upload field, accepted file types, name of the page field to store the upload in). This reduces duplication, makes your code shorter and easier to understand and maintain.
    1 point
  19. Thanks! This seems to work pretty well. But its a big module for such a little problem ...
    1 point
  20. Hi! Wanted to know if anyone has a more elaborated guide on how to use Vuejs with Proceswirer for Process/Inputfield modules with hotreload and all the webpack nice thingies ? so that for example, I can view the process/inputfield module in development in the context of the ProcessWire pages/routes.
    1 point
  21. Now it does. ? Here you go: https://github.com/horst-n/PageImageManipulator
    1 point
  22. I can confirm that this method of replacing the decimal field worked on my e-commerce-Project where I tried this. No problems.
    1 point
  23. What is about starting at early state without that feature? Just with the possibility or limitation to use it for new (empty) projects? Who has said this: "Release early and often"? Don't remember. And yes, I know, there are not only pros with this strategy. ?
    1 point
×
×
  • Create New...