Jump to content


Popular Content

Showing content with the highest reputation on 10/09/2019 in all areas

  1. 5 points
    I would prefer cookies instead of sessions for such user-choices. Sessions expire when you close your browser, but cookies will still be remembered after x days (= the lifespan you define). You can set cookies with JS alone, so you don't even need a server / PHP for that.
  2. 4 points
    I build and use one template that is bound to a single page in PW where both are simply named "ajax". I can access it per URL "/ajax/" and use it for everything that needs to send or retrieve data in the background. Here is an example from a project where different forms send data that need to be validated first and then send to final (external) destinations. The client browser optionally gets back HTML like "success messages" or error descriptions. <?php namespace ProcessWire; /*============================================================================== XXXXXXXXXX :: site/templates/ajax.php 2019-07-04 ==============================================================================*/ /******************************************************************************* * * This template file handles form submissions that are raised via AJAX! * * Sanitize, validate, log and submit to final destinations. * * // how the used JS looks like $.ajax({ url : gAjaxUrl, // /ajax/ type : 'POST', async : true, dataType : 'html', // returned data has to be HTML data : submitData, // submitted data object success : function(markup) { if('' != selector) { // a selector string to match the $(selector).html(markup); // markup container } } }); ... * *******************************************************************************/ // only process AJAX calls if(!$config->ajax) return 'WRONG ACCESS METHOD'; // only process POST requests with valid required id if(!$input->post->hidden_id) return 'WRONG ACCESS METHOD'; // ... followed by all project specific validations etc. So, with your example I would check if there is a post value named theme, and if the value is one out of a whitelist of valid theme values: // does this belong to theme selection if($input->post->theme) { $validThemeValues = ['dark', 'light']; if(!in_array($input->post->text('theme'), $validThemeValues)) { header('HTTP/1.1 403 Forbidden'); return; } $session->set('selectedTheme', $input->post->text('theme')); return; } // does this belong to another thing? if($input->post->anotherThing) { // first validate, then process data // ... return; }
  3. 2 points
    Yo Ryan and everyone, I don't use ProcessWire anymore for new stuff — the size and scope of the projects makes using a database nonsense — but there is one half internal system that happily chugs along, for 7 years now (I think? Maybe 8 years?) Latest page ID created was 38047 😎 So, thank you for everything — mostly for keeping my job while "new system" isn't happening 😄
  4. 2 points
    echo $page->render; Just take into account that this will render the header and footer if you have included them on the child pages templates.
  5. 2 points
    + = shaky mySQL server / setup. There you have it. Maybe ask hosting support or switch to another DB if you can.
  6. 2 points
    Somehow I didn't consider this option at all! Thanks @dragan, I decided to implement this with cookies 🙂 And thanks to you too @horst, I'm sure this will come handy at some point!
  7. 2 points
    Not a problem — I create (and/or manage) around 20-25 sites a year. These are tiny, 1-5 page promo sites, all with bespoke, one-off design, and are either fully static, or connecting to a single "registration" system (which is atm running aforementioned PW). 90% of these are for an event, or an event series, so they start, last a while, and end anywhere between two months and half a year. I'm the only person editing them, and most of the edits happen straight in code. ATM, they are 99% built on Eleventy - https://11ty.io, and the fully static ones are built and deployed via Netlify, and the ones which are connecting to the registration system (via tiny bits of PHP) are deployed from the Github CI/CD to our own servers. I also (actually started this year) created/manage few long-term sites, which I've build on Kirby — It's basically a spiritual brother to ProcessWire, but fully file based, so it fits my development process better - I can sync the website up and down fully with git, without any need for managing the database. As for the system itself, I'll write up a blog post about it (probably) when I finish it, so I can post it here / send it to you later, but the short of it is I'm moving it to Laravel due to builtin support of PostgreSQL, queues and testing, and the rewrite will allow me to introduce a couple of design changes to overall system, which would actually be possible with PW as well (probably…), but if I'm going for a rewrite, I might as well go full rewrite.
  8. 1 point
    You may want to revise this line. 'get' will return only the first match. To return a page array, you need $pages as well. Try: <?php $children = $pages->find('template=onecolumn|twocolumn, sort=sort');
  9. 1 point
    Thank @adrian, just upgraded to ProcessWire 3.0.141 now back working, and everything seems to go faster...
  10. 1 point
    In 3.0.137 a new version of CKeditor was added. Maybe that's the reason. https://processwire.com/blog/posts/pw-3.0.137/
  11. 1 point
    Thanks for your super-fast reply. Indeed, adding first() will show the blogpost image. This is exactly I was looking for. Perfect!
  12. 1 point
    I think the main issue here is like you say, they images field is an array, so you have to grab the image you need (for example, the first one): $blogimages = $blogpost->images; $imgthumb = $blogimages->first()->size(500, 300); Double check your images field is actually showing up as an array. Best of luck!
  13. 1 point
    @Tyssen you could try to add <?php namespace ProcessWire on the top of the module file.
  14. 1 point
    Hi Teppo, thx a lot for your thoughts 🙂 Almost 🙂 Technically it's 2 parts: 1) The module (framework) that lives in /site/modules and provides helper functions (just like the pw admin), eg $theme->assets->render() that could render all js scripts and css styles in the head (that can be populated easily in all your templates via $theme->assets->add("assets/main.css"); $theme->assets->add("assets/main.js"); 2) The theme files that live in /site/templates/yourtheme and provide all the markup generation blocks (the basic setup is very similar to the default site profile). These files can easily be pulled from github. 3) Optional: Theme customizations, eg /site/templates/mythemechanges that only provide those files that are different from the master theme (eg a custom logo). Technically building themes is even possible at infinite recursion levels (themeMaster, themeChild1, themeChild2, themeChildN) where the first existing file is taken, starting from themeChildN (whenever it is requested as $theme->getFile("blocks/foo.php"); It's not about populating a $content variable in the theme files. It's more about providing the presentation layer (views) that can be shared across projects. The logic still has to be built into every single project, but with the huge difference that it will be as simple as that most of the time: <region pw-replace="header"> <?= $theme->render("blocks/menu.php") ?> </region> In the example above I'm just using the $content variable of the default site profile, but that just shows how flexible this approach is and that's by no means a necessity! 🙂 In other words: In the example above I'm using the business logic of the default site profile just by including _func.php and the current template file and I'm using 2 presentation layers, first the default uikit theme (the bright one) and then the second theme with the default and secondary uikit colors. Trust me, I've been there 😉 😛 And I disagree (but also not meant in a bad way). ProcessWire gives us the freedom to build things the way we want and that's what we all love it for, don't we? 🙂 The problem that I see with those markup generation modules is that they are either opinionated about the output (only support one framework) or don't look good or are just not easy to use. I'm building all my sites with uikit, so it's tedious to create a menu like this: $options = [ 'active-class' => 'uk-active', 'child-item-template' => '<li {class}>{title}</li>', ... ]; $modules->get('WhatSoEver')->render($options); Why? Because I'm not clever enough to always remember the correct markup/syntax and the module has other defaults (because the module author might not use uikit) and I'm doing this waste of time (and fun) over and over again... Actually I've not done too much frontend stuff, but I try to avoid repeating work as much as possible 😅 But you got a valid point here and I'll think about that more closely (what should be part of themes and what should be a separate module). Well, that's a good thing as it means that we are not building the same thing twice 🙂 But I'm still not sure about it. See the explanation about the $content variable above. Isn't that separation of concerns in the way you mean it? It would also be easy to provide a similar feature to RockThemes that calls a Controller file before it renders the template/block (or view, if you want to call it like that). Eg you could have the template file /site/templates/yourtheme/blocks/header.php <region pw-replace="header"> <div uk-grid> <div><?= $logo ?></div> <div><?= $menu ?></div> </div> </region> And then you could have a controller file /site/templates/yourtheme/blocks/headerController.php: <?php namespace ProcessWire; class headerController extends themeController { public function renderMenu() { return '<ul><li>...</li></ul>'; } public function renderLogo() { return '<a href="..."><img src="..."></a>'; } } I think I like that concept... But I have to think about it 🙂 Same with RockThemes 🙂 Yes, that sounds like finally we are talking the same language 🙂 Extending themes could either be done just by replacing a content block (by just placing a file with the same name in your child theme) or - don't forget about we are still using ProcessWire 😄 - hooks! <?php $theme->addHookAfter("render(blocks/footer.php)", function($event) { $event->return .= "<div class='uk-text-center'>Hello World added by Hook</div>"; }); Or something like this: <?php $theme->addHook("HeaderController::renderFoo", function($event) { $event->return = 'BAR!'; }); Would be great to hear what you think about all that, thx! 🙂 Have a great week everybody! PS: Another story that would make a lot of sense once we have some kind of standard in the frontend just like we have in the backend ($config->scripts->add(...)) would be some kind of site builder features. I've talked about that with @Jonathan Lahijani as he has put huge effort on that topic during the last year.
  15. 1 point
    Hi @teppo! Thx for your elaborate answer 🙂 Thx, this sounds like the name of my module and the headline of this topic is somewhat misleading. Actually my take is closer to WireFrame than to WordPress Themes. Or maybe it is something in between. Well. I don't like site profiles 🙂 Actually, I hate them 😅 Site profiles are so rigid and one-way. What if I developed a new project, started with my great profile and implemented a new feature (like new SEO markup that was not supported yet. I'd have to implement that feature on my site, then I'd have to update my site profile if I wanted to use this feature for future projects. And then? What happens to the 10 sites that I've built using this site profile during the last year? I'd have to update all of them one by one. What I want is to implement a feature once and then just do a git pull to update all instances. Maybe I'm overengineering, though... I think our approaches are quite close. I might have only been missing the site-profile part when I played around with WireFrame. So I ended up with a blank site and thought: "Ok, that's not too much of help or not really what I wanted." The idea of RockThemes is to provide a framework on the one hand (with a helper class just like ryan has the uikit helper functions file), but in addition to that themes could also provide basic page blocks that one needs over and over again. In contrast to WordPress Themes this could be files that are completely decoupled from the site's field setup. An uikit slider for example could look like this: /site/templates/themeMaster/blocks/slider.php <?php // defaults if(!isset($images)) $images = $page->images; ?> <div class="uk-position-relative uk-visible-toggle uk-light" tabindex="-1" uk-slider> <ul class="uk-slider-items uk-child-width-1-2 uk-child-width-1-3@s uk-child-width-1-4@m"> <?php foreach($images as $image): ?> <li> <img src="<?= $image->url ?>" alt=""> <div class="uk-position-center uk-panel"><h1>Foo</h1></div> </li> <?php endforeach; ?> </ul> <a class="uk-position-center-left uk-position-small uk-hidden-hover" href="#" uk-slidenav-previous uk-slider-item="previous"></a> <a class="uk-position-center-right uk-position-small uk-hidden-hover" href="#" uk-slidenav-next uk-slider-item="next"></a> </div> This block (that can be shared across different projects and simply updated via git push/pull) could then be rendered in the theme like this: /site/templates/themeFoo/home.php <region id="main-slider"> <?= $theme->parent->render("blocks/slider.php", [ 'images' => $page->your_image_field, ]); ?> </region> This means that it would not be a problem at all if pages had different field names. I guess some of that is obsolet now? I think you also got the impression that I'm talking about WP-like themes?
  16. 1 point
    @tires Thanks! The meta tags need to be HTML encoded because they are rendered inside HTML tags. This is not an issue, the tags will appear correctly in Google. The "&auml;" you are seeing in the source code is not related to the character encoding, it is just a character being HTML encoded. Cheers
  17. 1 point
    If you want to add your own button value at the add button of a pagetable field, you only have to put this little piece of code inside your ready.php file. $wire->addHookBefore('InputfieldPageTable::render', function($event) { $table = $event->object; if(!in_array($table->name, array('datespagetable'))) return; $this->addHookBefore("InputfieldButton::render", null, function(HookEvent $event){ $button = $event->object; if($button->name == 'button'){ $button->attr('value', 'Test'); } }); }); In this case I limit it to a certain pagetable field called "datespagetable". You have to change it to the name of your desired pagetable field. If you want to change it for all pagetable fields (no restrictions) simply remove the following line from the code: if(!in_array($table->name, array('datespagetable'))) return; If you want to add it to more than 1 pagetable field, then write all the fieldnames into the array: if(!in_array($table->name, array('datespagetable','pagetable1','pagetable2'))) return; You can change the value of the button text to your needs in this line of code: $button->attr('value', 'Test'); I simply called it "Test" in this case to show how it is working. If you need it to be a translateable string simply use: $button->attr('value', __('Test')); And now this is the result: This let you customize your pagetable field a little bit. Fe you can use "Add News" or "Add new events" or something else. If you want to change another attribute than the value please take a look at the following page: https://github.com/processwire/processwire/blob/master/wire/modules/Inputfield/InputfieldButton.module Best regards
  18. 1 point
    Thanks alot @Juergen! If you wan't to name the button automatically based on the page-table label or the label/title of the allowed templates, use this hook: $this->addHookBefore('InputfieldPageTable::render', function ($event) { $table = $event->object; // Make sure only for fields with a single template… if (count($table->hasField()->template_id) > 1) { return; } // Use the field label… $label = $table->hasField()->label; // or… use the template label or title… $label = $this->templates->get(['id=' => $table->hasField()->template_id])->get('label|title'); // don't miss the use($label part)… $this->addHookBefore('InputfieldButton::render', null, function (HookEvent $event) use ($label) { $button = $event->object; if ('button' == $button->name) { // add label and translatable Add string… $button->attr('value', __('Add') . ' ' . $label); } }); });
  19. 1 point
    You will need: ProcessWire (of course) ProcessWire ProCache ProcessWire Modules as you like and need Netlify Account (in my case, you can use any other hosting or Github pages) Git Account (Gihub, Gitlab, Bitbucket) ScreamingFrog (free version should fit most needs) Things to keep in mind FormBuilder will not work (out of the box) 40x/50x must be defined separately Redirects must be defined separately Module-based functionality will not work GDPR/Opt-in/Cookie consent must be added differently Avoid using core/module files (UIKIT, jQuery, CSS, etc.) Where to save files and how to address them Most content and design related files can be saved in ProcessWire itself. Logos, favicon, trust icons and whatsoever. Some files can't be stored in ProcessWire - or shouldn't be stored in it - fonts and sitemaps (XML) in my case. While developing the overall site always use relative paths and URLs. Fonts and other assets need to be addressed by their web-root-based path (/site/templates/myassets/font.ttf and so on). Internal linking should be relative as well. Otherwise you have to change those link URLs manually which is PITA. Which files to copy and where you find them As we use ProcessWire we want and should use everything we can to make our webdev life easier here. Let ProcessWire and some modules do the work while harvesting the results for our benefits. While ProCache takes care of generating minified CSS and JS, SEO Maestro generates a nice and handy sitemap.xml. Depending of your installed modules you want to (at least) double check the output and results in your static site. As already mentioned FormBuilder and Simple Contact Form will not work, 404 management and redirects by the awesome Jumplinks modules will not work, too. Instead you have to create your very own .htaccess file with all redirects and error documents. Other modules like MenuBuilder, SEO Maestro and some other modules do a pretty good job even in your static site as their benefits result in already rendered HTML/pages. Autolinks, Automatically link page titles and Share buttons are some modules that will work as well. While it didn't work for me it may work for you - the Cookie Management Banner module. I had some issues and decided to install and use Cookie Consent manually. The Workflow First of all build your site. Make it perfect. Do whatever you or the client wants or needs. Whenever possible look into your rendered HTML and cached pages. Take a closer look at all the URLs and paths. It's already a good idea to run ScreamingFrog and find out if there are any files missing, links broken or pages missing. When everything is done, clear all cached files, all minified JS and CSS. Start a ScreamingFrog session and let it run. It will visit each and every page on your site it can find. Hidden pages, orphaned pages and of course drafts and pages behind JS-links will not be found and therefore cached by ProCache. Look into /site/assets/ProCache-XXX/ and /site/assets/pwpc/ now and double check that there are your pages and JS/CSS files. You will need those afterwards. If everything is fine you have to copy things around now. The Setup - folders and structure In my case the easiest way to go was setting up two local sites - one with ProcessWire and another one with the static files, assets and other things I needed. In the examples below only relevant parts are listed. project.pw.test (ProcessWire) /sitemap.xml (Generated by SEO Maestro) /site/assets/files/ (copy the whole path) /site/assets/pwpc/ (copy the whole path) /site/assets/ProCache-XXX/* (copy only the content of this folder - all files and folders) /site/templates/myassets/ (copy the whole path) project.sv.test (Static version) .htaccess (for redirects and 40x/50x error pages) 40x.html 50x.html /sitemap.xml /site/assets/files/ /site/assets/pwpc/ /site/templates/myassets/ all files and folders from /site/assets/ProCache-XXX/ As you can see there are only a few things to copy. When you're done with copying these files to the static version of your project, open it up in your browser. Check for missing files and test it. Let ScreamingFrog do the most work and check for any kinds of errors. Fix them in your ProcessWire-site and copy and test again. Check your 404s, your redirects and everything else you would normaly test. Create checkafterupdate.txt and write down whatever went wrong in your first try. This will be a great checklist later. The Final Step As everything is copied now and at its correct place you can upload it to your host. In my case the static version is a private git repository on github.com. I can commit and push my changes there and Netlify takes care of publishing the new version - most of the time within seconds. The benefit of using git - compared to S/FTP - you always have some kind of control if something brakes and you have to revert and check changes. In my case it's Netlify but you can use Github pages or any other hosting solution you want/the client pays for. Be careful with GDPR-related things as DPAs. You have to have them in most cases - Netlify did a great job here and I found everything I needed, while Github disqualified itself back then due to missing documents and kind of a sluggish support. Questions? Ask.
  20. 1 point
    Could you try something like this? // only allow access to the page if logged in with editing permissions // otherwise throw a 404 if viewed directly if(!$page->editable() && (!count($options['pageStack']))){ throw new Wire404Exception(); }
  21. 1 point
    It's not quite that simple for a few reasons. Repeater pages are not directly accessible for non-superusers meaning that selector won't work for guests. So you'd need to specify "include=all", but then you'd also need to exclude any unpublished or "ready" repeater pages with "status!=unpublished". Also, the selector would match all repeater items from that field from all pages, when probably what is wanted is only items from one page. So then you'd need to match repeater pages under only one parent, maybe by building the name of the parent from "for-page-" plus the ID of the page you want the repeater items from. But the simplest way and only marginally less efficient is to match by the IDs of the repeater pages in the field value: $results = $pages->find("id=$page->feedback_repeat, include=all, limit=10");
  22. 1 point
    @OLSA Thanks for your insights. After reading many github comments and parts of the documentation and also trying out different things, I want to summarize some conclusions: CKEditor is not an HTML editor. It is a content editor and HTML is just one of the possible outputs. (From the lead developer) CKEditor 4 uses the DOM as a model. When loading data, the HTML is processed (read – filtered, normalized and escaped) but it ends up in the DOM anyway. CKEditor 5 has a custom data model. When you load HTML into the editor, it's parsed and then features (initialized previously in the editor) try to pick up from this HTML the pieces they understand. This is called "conversion". As a result of a conversion, the content is being loaded into the custom data structure. The reverse process is executed when content needs to be rendered back to the DOM (either for editing or for data retrieval). Read the complete comment here https://github.com/ckeditor/ckeditor5/issues/592#issuecomment-335108129 There is no no "View source" button to edit the HTML output directly, because you are not working with HTML, but a custom data model instead. There is no option to insert custom tags or javascripts in the content. Or we have to use placeholders and replace them. Or someone writes plugins for them. Custom attributes like data-something on elements are not implemented atm but you could write a plugin to extend this feature. CKEditor 5 is not meant as a replacement or upgrade of CKeditor 4. There may be content loss if you try to use existing content produced by CKE4 in CKE5. Read https://github.com/ckeditor/ckeditor5/issues/592#issuecomment-399361490 Table Plugin is very basic. No option to add a class to the table or specific rows/cells 😞 No target attribute on hyperlinks, like OLSA said. You can not add classes to elements like paragraphs, or words, etc. You could develop a plugin for this, but this has to be done for every element as far as I understood. My conclusion is, that CKeditor 5 may not be the best option for most of us. I will close the feature-request on github with a reference to this comment.
  23. 1 point
    Hi, Got it solved myself. I use $p = $pages->find("template=repeater_yourRepeaterField, limit=10") rather than $p = $page->yourRepeaterField->find("limit=10"). Gideon
  24. 1 point
    I have the same problem. This is the error in Chrome: [Deprecation] Resource requests whose URLs contained both removed whitespace (`\n`, `\r`, `\t`) characters and less-than characters (`<`) are blocked. Please remove newlines and encode less-than characters from places like element attribute values in order to load these resources. See https://www.chromestatus.com/feature/5735596811091968 for more details. Does anybody know how to fix this? //Solution found: Change the code in "AllInOneMinify.module" in line 713 to: $_timestamp = ((int)$_timestamp + $file['last_modified']);
  25. 1 point
    First off, I won't stop developing ProcessWire unless I'm dead. But lets say that one of you showed up at my door and shot me, and then I'm gone for good. This is free software and you don't get any guarantees there, no matter what CMS it is or how big the community or adoption of it is. But what you do get is the source code and permission to use it and do with it what you need to. There is far more security in that than any proprietary or commercial system. We should all feel very lucky that this project has attracted such a capable development community around it (more than any project I've ever seen), and there are several guys here that are fully capable of taking over the project if I go down in a hang-glider crash. I'm always reluctant to list off people because there are so many people that contribute to the core and I don't want to forget anyone. Suffice to say, I may hold the keys to the master GitHub account, but this is a project of many developers, at least 5 of which are fully capable of taking over the project if I kick the bucket. I'm certain that some of these guys could do better than me with it. Please don't take that as an invitation to show up at my door with a weapon. But I would suggest this may be better odds than with the bigger projects you'd mentioned. Lets also point out here that ProcessWire is not WordPress–it does not need daily updating in order to keep running. Most sites I build with ProcessWire are running the version they are launched with. With ProcessWire, you do not need to upgrade your site every time a new version comes out. You can generally upload it and forget it, and it'll keep running till the site as long as the server itself is running. What other CMS can you say that for? (I can't think of any) Personally, I think adoption of something like Drupal, Typo3, Joomla, etc. is more of a risk, because you are dealing with a legacy platform – you are adopting technology from 10 years ago. You are also adopting something that is a target for hackers and spammers. WordPress is perhaps the biggest target, and something I've very apprehensive to setup for clients. Ultimately when a company chooses to adopt a legacy platform because "it's what the clients know" or [more likely] what they themselves know, it's a lazy decision. It's not looking out for the clients' best interests, and it's pursuing mediocrity. When you pursue mediocrity, you pay for it in the long run. There is no better testament to that than the legacy platforms that agency seems attached to. 1-3 years after installing [Drupal/Joomla/Typo3/WordPress/etc.] for the client, they are going to be looking for "something different" in terms of the CMS (we all know this) and they won't be coming back to the same agency. The agency that thinks it's playing it safe is really just hurting themselves when they give their clients something tired and mediocre that anyone can give them. Instead, give them ProcessWire, and they'll know you are different and better (a secret their competition does not have), and they'll be a lifetime client.
  • Create New...