Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 11/02/2018 in all areas

  1. This week, ProcessWire 3.0.118 contains several updates and this post covers them all. The most significant update is a useful new addition for viewing and manipulating page redirects, right from the page editor: https://processwire.com/blog/posts/processwire-3.0.118-core-updates/
    11 points
  2. We have relaunched the old website of design business expert Joachim Kobuss. The old site desperataly needed a facelift and a streamlined CMS that allowed our client to fill over 130 pages of content in a span of two weeks. We at schwarzdesign used ProcessWire + ProFields for the Backend and built a Bootstrap 4.1-based frontend. Features / Services provided Responsive design featuring a desktop layout with two fixed navigation areas and a fixed sidebar that form a frame around the content. Carefully set typography and spacing for a smooth reading experience for long texts on all devices. A hierarchical page tree with three levels of nested pages, all using the same simple set of fields. Password protection for individual pages and an optional password request form. Privacy by design: There's no tracking, no Google Map, no Facebook Like Button or anything like that on the page. Because we don't set any cookies or include third-party code, we don't need a cookie notice ? Modules used Profields (especially Repeater Matrix, Textareas and Functional Fields) Form Builder Tracy Debugger Wire Mail SMTP Duplicator Admin Links in Frontend Sitemap Optimizing for content The most distinguishing feature is the large amount of long texts our client has written. So it was important to provide a good editing experience in the frontend and have a content centered design that made long text sections easy to follow. We didn't want to give our client just a large CK Editor body text, since in our experience, those WYSIWYG editors aren't actually that easy to use for non-technical folk. It also reduces the amount of control we as designers and CSS-authors have over the presentation of the content. So instead, we built a flexible section system using the Repeater Matrix field of the ProFields module. There are three sections: text content, downloads and single image. Each section has a headline field and a radio selection field to switch between two levels of headline hierarchy (corresponding to h2 and h3). For the text section, there's a CK Editor textarea stripped to the bare minimum (strong, italic, lists, blockquotes and links), with no confusing styles or format dropdown. The image section features an additional option for full- or half-width images and an option to display the image description as a caption. And of course, the download section has a multivalue file field that is displayed as download buttons in the frontend. This simple sectioning system allowed us to build the entire site (except for the homepage) using just one template fieldset. There are three templates: Basic Page, Topic and Article. Basic pages are for generic pages like imprint and data policy. Topics may only be children of the homepage, while articles may be children of a topic or of another article, so the pages can be nested indefinitely. This provides the hierarchical structure used for the page layout. Topic and article inherit the fieldset of the basic page, so it's just one template under the hood. There's also smart Open Graph tag generation; title, description and preview image are automatically generated based on the first suitable sections on each page and can be manually overridden using the SEO tab available on all pages. Laying out the page Our design has three fixed areas: The top navigation, the left side navigation and the right sidebar, which shows some general contact info and a random image. The top navigation always shows the top-level topic pages, the sidebar navigation contains all articles in the current topic, displayed in a hierarchical structure. This was technically challenging, as the many fixed layout areas broke the normal pageflow and didn't work well for smaller devices. I solved this using four seperate Bootstrap containers, three of which are fixed. Only the container with the main page content flows normally. The left sidebar only fills the three leftmost columns of its container, the right sidebar the three rightmost columns, and the main content takes up the six center columns of it's container. All three have an offset to the top to make space for the fixed header navigation. This way, all the seperate layout areas can never overlap. The CSS that applies position: fixed to the containers is wrapped in a media query with a min-width, so on tablets and mobile devices, the areas simply stack. Check out the source code to see how those containers are laid out! The logo is text by the way, not an image. It's positioned using CSS3 transforms. Password protection Our client wanted to password protect some of his pages with varying passwords, so he can give different people access to different sets of pages. Also, he wanted to have a password request form, where people can submit their name and contact information to request access to a specific page. In the backend, we added a password field that activates the password protection for that page. There's also a checkbox to display the password request form. The form is built using the Form Builder module (and a simple hook to add the current page title to the outgoing mail). However, for the password protection, we built a custom solution. While there is a readymade module available, we didn't want something based on user accounts. A visitor should be able to simply input the password on a protected page and start reading, without bothering with registering an account. The authentification is stored in the session, so after closing the browser you have to input the password again, but that seemed to be a worthy tradeoff. Anyway, when visiting a password protected page, the template checks if the user is already authentificated to read this page; if so, it displays the page content, otherwise it displays the password input form and the password request form if it was also activated in the CMS. A nice-to-have feature that we built in addition is that if multiple pages use the same password and you input it on one of them, you are automatically authentificated to view all of them during the current session. A caveat of this method is that since the page content depends on the current session, we couldn't use the inbuilt page cache at all. So instead we used the cache API to cache rendered section markup and the navigation menues, which still results in a blazingly fast site. For the techies amongst you, here's the PasswordProtectedPage class we wrote for this functionality: <?php namespace schwarzdesign; use Processwire\Wire; use Processwire\Page; use Processwire\PageArray; use Processwire\User; class PasswordProtectedPage extends Wire { const PASSWORD_FIELD = 'page_password'; const PASSWORD_INPUT_NAME = 'page_password'; const STORAGE_KEY = 'authentificatedPages'; const STATUS_FREE_ACCESS = 'free_access'; const STATUS_AUTHENTIFICATED = 'authentificated'; const STATUS_NOT_AUTHENTIFICATED = 'not_authentificated_yet'; const STATUS_WRONG_PASSWORD = 'wrong_password'; /** * The status of the authentification. */ public $status = self::STATUS_NOT_AUTHENTIFICATED; private $page; private $authentificated_pages = []; public function __construct(Page $page) { $this->page = $page; $this->authentificated_pages = $this->getAuthentificatedPagesFromStorage(); } public function handleRequest() { // pages with no password set if (empty($this->page->get(self::PASSWORD_FIELD))) { return $this->status = self::STATUS_FREE_ACCESS; } // pages that the user is already authentificated to use if (in_array($this->page->id, $this->authentificated_pages)) { return $this->status = self::STATUS_AUTHENTIFICATED; } // if the user set the input, check the password if ($password = $this->getInputPassword()) { if ($this->passwordIsCorrect($password)) { $this->authentificatePagesByPassword($password); $this->storeAuthentificatedPages(); return $this->status = self::STATUS_AUTHENTIFICATED; } else { return $this->status = self::STATUS_WRONG_PASSWORD; } } else { return $this->status = self::STATUS_NOT_AUTHENTIFICATED; } } public function userCanAccess() { return in_array($this->status, [self::STATUS_AUTHENTIFICATED, self::STATUS_FREE_ACCESS]); } public function getInputPassword() { $password = $this->wire('input')->post(self::PASSWORD_INPUT_NAME); if (empty($password)) { return null; } return $password; } public function authentificatePagesByPassword(string $password) { $pages = $this->wire('pages')->find(self::PASSWORD_FIELD . '=' . $password); $ids = array_map(array($this, 'extractIdFromPage'), iterator_to_array($pages)); $this->addAuthentificatedPages($ids); } /** * Private helper Functions. */ private function passwordIsCorrect(string $password) { return (string) $this->page->get(self::PASSWORD_FIELD) === $password; } private function extractIdFromPage(Page $page) { return $page->id; } private function addAuthentificatedPages(array $page_ids) { $this->authentificated_pages = array_merge($this->authentificated_pages, $page_ids); } private function getAuthentificatedPagesFromStorage() { $ids = $this->wire('session')->get(self::STORAGE_KEY); return $ids ? $ids : []; } private function storeAuthentificatedPages() { $this->wire('session')->set(self::STORAGE_KEY, $this->authentificated_pages); } } This is used in the template like this: <?php namespace Processwire; use schwarzdesign\PasswordProtectedPage; $protectedPage = new PasswordProtectedPage($page); $protectedPage->handleRequest(); if (!$protectedPage->userCanAccess()) { if ($user->hasPermission('display-page-password')) { /* Display the password in plaintext for editors & admins */ } /* Display the password input form */ if ($page->show_password_request_form) { /* Display the password request form */ } } else { /* Display the page content */ } Screenshots
    5 points
  3. @PWaddict https://github.com/processwire/processwire/blob/dev/wire/modules/AdminTheme/AdminThemeUikit/AdminThemeUikit.module#L43 Change it to false.
    5 points
  4. I'd vote strongly against that. Like who's to decide which 3rd party modules are worthy to be featured in the (1st party) docs? Who's job is it to maintain those docs if things change? Will modules be removed if they loose popularity? When exactly would that be the case? — I doubt we should put even more work on ryan's shoulders especially for stuff he might not even know very well. As afaik the module directory does not track downloads we cannot have a most downloaded modules listing, but imho that would be a more useful way to highlight modules, which are popular and not to be missed. We could also have a modules of the month poll or something like that for gathering information on module usage. As for documenting what a module does and how it's used; that should be up to the module maintainer and/or the community. Maybe the api docs could pull them out of the source code automatically like it does for the core (how it could work [1]). The point is the core docs are certainly not the place for providing information on 3rd party modules. 1: hexdocs.pm (try searching for e.g. phoenix or ecto for the best maintained examples) Each package of the hex package manager does automatically generate it's docs on publish and they will be published to hexdocs.pm. The docs are generated from the package's source code by a similar system to how it works for processwire. From my experience with it I've to say that having one platform for hosted docs, which are autogenerated (in 99% of the cases even by the same generator) is a real incentive to write (good) docs.
    5 points
  5. @bernhard Just tested on 3.0.117 d($this->wire->modules->find('name^=Inputfield')); d($this->wire->modules->find('name^=Inputfield')); Both return 37 items. Is it specific to 'UikitTheme' names?
    3 points
  6. Then your server doesn't have time zone data installed. If you can add that, you can assign a zone name and don't have to adapt the offset every time DST changes. Glad to hear you got it solved though ?
    3 points
  7. Thanks @Robin S PR merged and modules directory updated.
    2 points
  8. Something similar is now built into the core: https://processwire.com/blog/posts/processwire-3.0.118-core-updates/
    2 points
  9. That result in a 500 server error. I changed it to the following and now I'm getting the proper time on backend's creation, modification, installation times etc. $config->dbInitCommand = "SET NAMES '{charset}', time_zone = '+02:00' "; Your DatetimeAdvanced module helped me with that ?
    2 points
  10. Since every hosting company can basically configure their servers as they wish, it would be wise to ask them directly. On some hosting environments, you can add PHP/Apache customization via control panel, on others you have to add a user.ini file in your site's root directory. With others you have to use .htaccess. But which methods are allowed or not, can surely be answered by their tech support team.
    2 points
  11. This module provides a way to rapidly generate Page fields and the required templates and pages for use as a drop down select (or any other Page field type). This module will let you create a full page field setup in literally a few seconds To use, run Page Field Select Creator from the Setup Menu Enter a Field Title, eg: Room Types Select Options - These will become the child pages that will populate the page field select options. There are two different options. Option 1. TITLE FIELD ONLY - enter one option per line, eg: Single Double Suite Option 2. MULTIPLE FIELDS - the first line is used for the field names and the first field must be 'Title'. Subsequent lines are the values for the fields, eg: Title, Number of Beds, Number of People, Kitchen Facilities Single, 1, 1, Fridge Only Double, 2, 2, Fridge Only Suite, 3, 6, Full Kitchen Choose the parent where the page tree of options will be created, eg a hidden "Options" parent page Select a "Deference in API as" option depending on your needs Choose the input field type Check whether "Allow new pages to be created from field?" should be enabled. As an example, if you entered "Room Types" as the field title, you would end up with all of the following automatically created: a fully configured page field called: room_types MULTIPLE FIELDS OPTION - 3 additional fields - number_of_beds, number_of_people, kitchen a parent template called: room_types a child template called: room_types_items (with either just a title field, or with the 3 additional fields as well) a parent page called: Room Types a series of child pages named and titled based on the per line entries in the Select Options textarea The templates are configured such that the "room_types_items" child template can only have the main "room_types" template as a parent, and vice versa. Then all you have to do is add the newly created page field to any template you want and you're ready to go! You can grab it from: Modules directory: http://modules.processwire.com/modules/process-page-field-select-creator/ Github: https://github.com/adrianbj/ProcessPageFieldSelectCreator
    1 point
  12. Here is my first processwire module (beta). https://github.com/theo222/ImagePickerField A lot of "first times". First time Github, Markdown and of course PW Modules. So be gentle please. I hope it works.
    1 point
  13. I solved my external filter setup with a checkbox (edited the original code block with the changes) and I am happy! I can create a series of screenshots during the weekend to illustrate how it works ?
    1 point
  14. Interesting, thx @Zeka it also works on a different install ? Ah, I guess that's because I set them to be singular... Yes, just checked that: The minimal theme is loaded also on the second run now that I changed "singular" to FALSE. Is that the expected behaviour? Not sure if that makes sense and how this singular feature could maybe affect code also in other szenarios...
    1 point
  15. Just pushed v0.0.14 to github - caution, there is a BREAKING CHANGE (but a small one ? ) Initially I implemented a concept of column definition plugins to reuse column modifications ( for example you almost always want icons to show/edit/delete the row instead of showing the page id). Now that works with helper functions that are available through the RockGrid.colDefs object (and you can of course extend that with your own helper functions). It's easy to create those functions: document.addEventListener('RockGridReady', function(e) { RockGrid.colDefs.fixedWidth = function(col, width) { col.width = width || 100; col.suppressSizeToFit = true; return col; }; }); And using them is a lot easier than before: // before grid.addColDefPlugins({ id: 'rowactions', }); var col = grid.getColDef('id'); col.headerName = 'ID'; col.width = 70; col.suppressSizeToFit = true; col.suppressFilter = true; col.pinned = 'left'; // after var col = grid.getColDef('id'); col = RockGrid.colDefs.rowActions(col); col.pinned = 'left'; It will replace your ID with those icons: There are plugins available to add your custom actions to that column (or any other column) and you can even combine those plugins: col = grid.getColDef('title'); col = RockGrid.colDefs.fixedWidth(col, 100); col = RockGrid.colDefs.addIcons(col, [{ icon: 'file-pdf-o', cls: 'pw-panel', dataHref: function(params) { if(!params.data.pdfs) return; var pdfs = params.data.pdfs.split(','); if(!pdfs.length) return; return '/site/assets/files/' + params.data.id + '/' + pdfs[pdfs.length-1]; }, label: function(params) { return 'show invoice PDF ' + params.data.id; }, }]);
    1 point
  16. @ryan Thanks for updates. In the blog post for 3.0.117 new 'WireArray::new' method was introduced but in 3.0.118 it was removed and now we have new API functions (WireArray($items) and PageArray($items). Maybe the blog post for 3.0.117 should be changed to reflect current implementation (as blog posts currently are part of docs)?
    1 point
  17. Like here for the module version ?
    1 point
  18. Thanks for sharing! Awesome site ? I wonder why you didn't create a module for that. There was a discussion about that recently: But in your case I think it would make sense to pack it into a module. You could then: update it with one click across several websites extend the $page object via hooks instead of creating a new class share it with the community via github&co and the modules directory This: <?php namespace Processwire; use schwarzdesign\PasswordProtectedPage; $protectedPage = new PasswordProtectedPage($page); $protectedPage->handleRequest(); if (!$protectedPage->userCanAccess()) { [...] Would then become that: <?php namespace Processwire; $page->handleRequest(); if(!$page->userCanAccess()) { [...] And it would be really easy to achieve in your (autoload) module: $this->wire->addHook("Page::handleRequest", function($event) { // your code here }); I think you could even get rid of the "handleRequest" call and do that automatically in the background.
    1 point
  19. Maybe the place for such resources would be the blog - just like we already do (and did: https://processwire.com/blog/posts/introducing-tracy-debugger/ )
    1 point
  20. Yep, works well here. New PR made.
    1 point
  21. Valid points! Download statistics and opening the system we already have for the API docs to 3rd party modules would be awesome!
    1 point
  22. @Robin S - I wonder if a simple temporary solution might be to turn off error reporting at the top of the Adminer process module file?
    1 point
  23. To remove the 'pass', 'email', 'roles', and 'language' fields from the user_copy template, I had to temporarily disable their "system" and "permanent" statuses for each field by unchecking the related options in the Advanced tab of Edit Field. After this, I was able to complete the step 3 successfully.
    1 point
  24. Instead of doing this, try the following instead: 1. In /site/config.php set $config->advanced = true; 2. Create your user_copy template (whatever you want to call it) 3. On the "Basics" tab of Edit Template, select "user" for "Fieldgroup" and save. 4. Remove the line you added in step 1. Now the user_copy template will always have the same fields as the user template.
    1 point
  25. Done. Not sure, but I wonder if it's related to the PHP notices from Adminer & plugins I mentioned earlier in our PM conversation. Maybe with debug mode on the error reporting level changes and those notices are being output somewhere before session start.
    1 point
  26. Done. Knowing very little about the subject or the website, I had to guess about 10-20% of the items, e.g. I have no idea what "RAAF C-17 Globemaster" actually is (of course, I could have googled it, but I'm a bit short on time right now...)
    1 point
  27. New "Adminer" database GUI panel just added. A huge thanks to @Robin S for making me take another look at this long forgotten tool and for helping with many suggestions regarding the implementation in Tracy and debugging several issues. There is one outstanding one on his local Windows dev setup that I can't reproduce at all and he also isn't seeing on a live server. He is getting session_start / headers already sent error. Could someone else on Windows (maybe @bernhard) take a look and let me know if you have the same problem as well. Actually Robin - any chance you are running the SessionHandlerDB modules on that local setup? The color scheme is configurable in the Tracy settings. I have used this already on a live server to help debug something and it would have taken much longer to go find the cpanel credentials, and navigate my way to PHPMyAdmin. This logs you in automatically and is virtually instant. I am away for the next 10 days so if you find any problems, they will most likely have to wait till I'm back. Hope you find it useful!
    1 point
  28. I love debates ? Jokes aside, some simple features would do I think: a button to prefix the topic's title with either [open], [solved], [closed], etc... a button to highlight replies which – a forum users thinks – SOLVE the issue, rather than being "the best". What is "best" anyway? Ask the guys at Apple, they'll tell you what best is... ?
    1 point
  29. Ryan, you're an absolute champ for grinding away on the documentation. We all know it's a developer's favourite task. But seriously, thank you.
    1 point
  30. @joshuag Are there any updates on this awesome module already? Can't wait to try it.
    1 point
  31. I love the new Foundation for Emails. If you are using the sass version, it is super easy to set up and start coding. You really don't even have to mess with tables etc as the stack takes care of parsing all of that when you "foundation build". I did a test the other day in litmus with multiple columns etc and I had no issues across the board.
    1 point
  32. http://foundation.zurb.com/emails.html (Formerly Ink) http://tedgoas.github.io/Cerberus/
    1 point
  33. PageTables are handled the same as other pagefields. So you can just use something like this: $selected_page = $pages->get("something"); // Get the Page $selected_table_entry = $selected_page->table->eq(0); // Get the PageTable entry $clone = $pages->clone($selected_table_entry); // Clone the entry $new_page = $pages->get("something"); // Get the page to copy to $new_page->table->add($clone); // Add the clone to the PageTable $new_page->save();
    1 point
×
×
  • Create New...