Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 01/14/2017 in all areas

  1. This week we take a look at a new template file output strategy available in ProcessWire 3.0.49+. (Not to be confused with a “template system” like Twig or the like, as our template system is PHP). This strategy is an experimental but super-simple new alternative to direct output and delayed output, and in some ways a combination of both. Yet it’s likely to be more accessible for front-end developers and newcomers to ProcessWire, without sacrifices. Have a read and let us know what you think. https://processwire.com/blog/posts/processwire-3.0.49-introduces-a-new-template-file-strategy/
    5 points
  2. https://towait.com/blog/processwire-field-template-module/ http://page-online.de/tools-technik/processwire-ist-ein-schlankes-und-flexibles-cms/
    4 points
  3. This is freaking awesome - I love it! I've always disliked working with HTML markup inside PHP variables - the sacrificed readability of the HTML that comes with multiple variable concatenations, the single quotes/double quotes/escaped quotes hassle. I try to avoid it as much as possible using output buffering but this new feature suits me down to the ground and will definitely be my preferred way of managing markup in templates going forward. Simple and brilliant, like the rest of PW. Thanks!
    4 points
  4. Default session lifetime is 86400 seconds. You can change this to any value you want. // config.php $config->sessionExpireSeconds = 86400; Allow/ disallow sessions (and the wire cookie) under conditions. Remind that you need this to have access to the backend admin. // config.php $config->sessionAllow = true; If you want to disable cookies only for the frontend /** * config.php * if we would use cookies only for the admin area * */ $config->sessionAllow = function($session) { // if URL is an admin URL, allow session if(strpos($_SERVER['REQUEST_URI'], $session->config->urls->admin) === 0) return true; // if there is a session cookie, a session is likely already in use so keep it going if($session->hasCookie()) return true; // otherwise disallow session return false; }; If you want to use cookies respecting EU Cookie law I recommend Cans Module MarkupCookieConsent in combination with this settings. /** * config.php * if we would use cookies only for the admin area * */ $config->sessionAllow = function($session) { // if URL is an admin URL, allow session if(strpos($_SERVER['REQUEST_URI'], $session->config->urls->admin) === 0) return true; // if there is a session cookie, a session is likely already in use so keep it going if($session->hasCookie()) return true; // user accepted cookies due to EU law (Module MarkupCookieConsent) if(!empty($_COOKIE['eu-cookie'])) return true; // otherwise disallow session return false; }; Use the core module SessionHandlerDB to store session vars in the database. Learn more about session setting options and sessions by reading the comments in the files /wire/config.php or /wire/core/Session.php of your processwire installation.
    3 points
  5. 3 points
  6. A Snipcart integration case study, as mentioned in the Showcase forum... Les Ateliers Fromagers: Custom Shopping Cart Integration on a ProcessWire CMS Site https://snipcart.com/blog/case-study-ateliers-fromagers-processwire Also on the Snipcart site: https://snipcart.com/blog/processwire-ecommerce-tutorial
    3 points
  7. Hello all ! Just because I'm proud to be featured by Snipcart (js ecommerce solution) about my integration on my Processwire based website ! This post talks about Processwire and how I've done it : https://snipcart.com/blog/case-study-ateliers-fromagers-processwire If you wanna take a look at my website : https://www.ateliersfromagers.com/ (french & english) Have a good day everyone ! S
    2 points
  8. Hello, I will try to respond these questions Questions 1, 2 and 4 could be resolved by using "Transformers" a "Transformer" is simply a class that convert data from one format to another. In this case a transformer that converts PW pages to rest json. And example. If you got a template named video that stores youtube videos and contains the following fields: url, title. You can create a Transformer named like transformers/youtube.php <?php namespace ProcessWire; class YoutubeTransformer { public $source; public __construct(Page $source) { $this->source = $source; } public function toArray() { return [ "url" => $this->source->url, "title" => $this->source->title ]; } public function toJson() { return json_encode($this->toArray()); } } That way you could create a special class that could render specific outputs depending on what do you need. For example {catID}/articleList/{articleID}/galleryList/{galleryID} You could have a specific transformer for categories, articles and gallery items and share the output for each class and join them in the final response. This could also be combined with field specific templates https://processwire.com/blog/posts/processwire-3.0.7-expands-field-rendering-page-path-history-and-more/ 3.- For answering this it depends on your architecture and your api requirements. The rule of thumb is think how the developers will use the api and what information they will need. 5.- Well depends on what do you need and feel more confortable, those are just helper methods. there are tons of good code that you could use like https://github.com/marcj/php-rest-service http://symfony.com/doc/current/bundles/FOSRestBundle/index.html http://symfony.com/components/Guard http://symfony.com/components/HttpFoundation http://symfony.com/components/Serializer
    2 points
  9. Sounds like you would want to handle 5 data types: boats rooms cruises customers bookings A boat I'm assuming has a fixed number of rooms. Perhaps start with a data model like this which takes everything into consideration: Boats (boats.php) Boat A (boat.php) Room 1 (room.php) Room 2 Room 3 ... Boat B Room 1 Room 2 ... Customers (customers.php) Customer 1 (customer.php) Customer 2 ... Bookings (bookings.php) Booking 1 (booking.php) Booking 2 ... Cruises (cruises.php) Cruise 1 (cruise.php) Cruise 2 ... Cruise template fields: title date boat (page-select to /boats/, boat.php) Customer template fields: first name last name (other typical fields) Cruise template fields: title boat (page-select to /boats/, boat.php) date Booking template fields: customer (page-select to /customers/, customer.php) cruise (page-select to /cruise/, cruise.php) rooms (based on cruise->boat, select for the rooms that the boat has) I'm assuming the interface would be PW's admin. Perhaps use some hooks and ListerPro to tie it all together. Make it as user-friendly as possible. Maybe have a page within the admin outputs each cruise with which rooms have been booked vs. unbooked which would be friendly to the site admins.
    2 points
  10. Found a pretty cool solution for this. Repeater + Page + Files. So I set up a repeater called langFiles. Inside that repeater I added a Page selector called lang and the files field. The page selector is set to be a single select, by template = language. So in the admin I get a repeater, add an item, select the language and upload the files. Add another one for the second language, and so on. Then on the frontend: // Somehow $page->langFiles->find('lang='.$user->language) doesn't work foreach ($page->langFiles as $lf) { if ($lf->lang == $user->language) { $filesRepeaterBlock = $lf; break; } } if ($filesRepeaterBlock->files->count) { echo '<ul>'; foreach ($filesRepeaterBlock->files as $file) { echo '<li><a href="'.$file->url.'" target="_blank">'.$file->name.'</a></li>'; } echo '</ul>'; } And there it is. Add a new language tomorrow, and it adapts. And it's not too weird for the admin.
    2 points
  11. By Ryan: "... the $config->userAuthSalt (which appears at the bottom of your /site/config.php file). That particular value is generated randomly when you first install ProcessWire. It is forever tied to the passwords as a secondary salt. It's not technically necessary to have it, and passwords are already blowfish'd, but I've always felt better having one part of the salt disconnected from the database itself. If that salt changes or is lost, then all the passwords are forever broken."
    2 points
  12. ImportPagesPrestashop You can download it here: ImportPagesPrestashop With this module you can import your categories, products, features and images of the products to your new Processwire website! What does it? Once you've installed this module, a new tab will be under the Setup named Import Products from Prestashop. When you click on it, you can make connection with your Prestashop DB. After making the connection you can import first the categories, followed by products and the features and the images will be inserted in the fields of the product that is linked to these features and images. You can choose whether you import your categories et cetera in as much languages as possible or only in your default language. You can also choose to import the EAN-number and/or the products and the Reference code of the products. Requirements Only tested it so far on Processwire 3.x. Installation Download the zip file, upload it to your Processwire site and install it. Languages If you want this module to run as smooth as possible, name your languages like in the screenshot below. If you want to execute this module in dutch, download the .zip file, go to your languages tab in processwire, go to your dutch language and upload that .zip file to your site translation files. Credits to djuhari NL-Translations.zip
    1 point
  13. Does this work on PW 3.0 though? One part says: It should. See: https://github.com/processwire/processwire-issues/issues/75
    1 point
  14. @flod and @Gideon So - I just committed a new version which automatically adds the Repeaters parent to the list of branch exclusions. I would appreciate it if you could please check if this takes care of image uploads in repeaters without having to manually add it in the config settings. Thanks!
    1 point
  15. When making a new booking, you have the 'room' dropdown (well perhaps it should be "Rooms" since one customer may be able to book more than one room) as I described, however you obviously don't want to a room to be double-booked, meaning that dopdown should only show available/unbooked rooms. You can determine that by writing a custom query for that ASM-select field (using PW's Custom PHP Code feature). I think the selector would be something like (well you'd need to finish it off and also make it handle whether the current booking has a room selected): // this will find all the unbooked rooms of the selected boat $wire->addHookAfter('InputfieldPage::getSelectablePages', function($event) { if($event->object->name == 'rooms') { $booking = $this->pages->get($this->input->id); $cruise = $booking->cruise; $boat = $cruise->boat; $allRooms = $boat->children; $availableRooms = new PageArray(); foreach($allRooms as $room) { if( ! $this->pages->count("write query here to determine if the room has been booked") ) { $availableRooms->add($room); } } $event->return = $availableRooms; } }); Hope this helps.
    1 point
  16. Let's throw in one more... How about using created_users_id/createdUser? It depends on your workflow though. Who creates the users? How are they created? Same for their respective pages. Doing it manually would mean your client heading over to settings tab when editing a page and changing the created user there (would have to be first enabled in the template). This may not be ideal. You could automatically change the created user ID using the API via an autoload module, but that depends on how the users are created since you want to synchronise the two actions. The advantage of this approach is that you can give your user pages whatever name you want to give them. You would use it like: if($page->createdUser->id != $user->id) {// @note: here you'd also need to add logic to let superadmin and some editor to have access :-) // don't allow access } // in a selector $userPage = $pages->get("template=members, created_users_id={$user->id}");
    1 point
  17. That's it! Thanks a lot, guys.
    1 point
  18. I have the same problem with repeater also. The solution is exclude the repeater page under admin in the module settings. Gideon
    1 point
  19. Thanks everyone. I wont worry about for now then, it's only a demo site. Does this work on PW 3.0 though? One part says: Compatibility 2.5, 2.6, 2.7 but further down says: This version of the profile exporter requires ProcessWire 2.5 or newer. Could do with understanding the modules information pages a bit better, has stopped me so far from trying anything so far. After Drupal though, it's so nice to be able to achieve so much already with no added modules at all, it's fair to say PW has really re-ignited my dwindling passion for web design again.
    1 point
  20. This is just an idea... You could consider making the creation and maintenance of these articles easier for site editors by having a simpler structure in the page tree (just the categories as parent pages), entering the article date with a datetime field, and then creating the desired URL for the frontend using URL segments (enable this on the category template). So your category template would look for the following URL segments: segment 1: year - sanitize to integer, throw 404 if out of range segment 2: month - sanitize to integer, throw 404 if out of range segment 3: day - sanitize to integer, throw 404 if out of range segment 4: article page name - throw 404 if no match for article page name In terms of finding articles that match a given year, month or day you could convert to a timestamp range as Ryan shows here, but to make it easier (and considering you'll need the integers for building the article URLs) I would instead add 3 integer fields to your article template, set the field visibility to "Hidden (not shown in editor)" and then populate them with a saveReady hook. // in /site/ready.php $this->pages->addHookAfter('saveReady', function($event) { $page = $event->arguments('page'); if($page->template->name === 'article' && $page->article_date) { $page->day = date('d', $page->article_date); $page->month = date('m', $page->article_date); $page->year = date('Y', $page->article_date); } }); Now it's really easy to find articles, e.g. $matches = $pages->find("template=article, year=2016, month=11, sort=sort"); For the question in your original post you'd do something like this: $latest_article = $pages->get("template=article, parent=/politics/, sort=-article_date"); $recent_articles = $pages->find("template=article, parent=/politics/, article_date={$latest_article->article_date}, sort=sort, limit=5"); $day_link = "/politics/{$latest_article->year}/{$latest_article->month}/{$latest_article->day}"; // use this as the first link to the 'parent' page When you need to output the URL of an article you would build it like this: $url = "{$article->parent->url}{$article->year}/{$article->month}/{$article->day}/{$article->name}/"; For convenience you'd probably make a simple function that returns this URL string. In the backend, rather than browse through the page tree, if you want to list articles by day/month/year you can use the "Find" lister. Or better yet a dedicated Lister Pro instance for articles.
    1 point
  21. @Tom., I think BitPoet's module is the way to go, but in case you can't use it (e.g. your MySQL doesn't have timezone support enabled) you could use a saveReady hook to populate a hidden field with the day of the week of the entered date. // in /site/ready.php $this->pages->addHookAfter('saveReady', function($event) { $page = $event->arguments('page'); if($page->template->name === 'act' && $page->date_field) { $page->day_of_week = date('l', $page->date_field); } }); // find pages $pages->find("template=act, day_of_week=Friday");
    1 point
  22. Sorry, it's apparently been too long since I tested the module with newer PW versions (turned out I was using an early 3.x release, but too much has changed since then), but I'm working on it. It's giving me a bit of a headache still, but I'll try to have it fixed over the weekend.
    1 point
  23. So many ways now to structure templates. Sounds definitely interesting, for the reasons @Robin S listed.
    1 point
  24. I have 20+ site-copies with the same authsalt. (Mostly dev and stage copies). It works. I haven't looked into it, but I believe it is generated by the installer script. (So for security it would be better to have more unique authsalts, but for temporary dev or stage copies, it is ok for me) You also may modify it in a way you like, but it should match the string-length and the allowed characters. Once you modified it in your site/config.php, you are not able to login with the existing accounts. But you can use the trick with resetting the password for the admin with a temporary codesnippet from within a template file. After that you can login as admin again, but maybe you have to resave / reassign passwords to the other user accounts, if any.
    1 point
  25. I'm not sure about generating a new userAuthSalt, but in the future if you want to reuse an existing site as the starting point of a new site then check out the Site Profile Exporter module.
    1 point
  26. Hi @Ivan Gretsky do you have the code? I have working pagination on a site and may be able to help. My (stripped down version) of news-index is like this: // news-index.php <?php $entries = $pages->find("template=news-entry, limit=9, sort=sort"); //9 articles per page $pagination = $entries->renderPager(); ?> <div class="page-tabs-wrapper"> <div class='page-tabs'> <div class='upper'> <?php echo $pagination; ?> </div> </div> </div> <div id='news-row'> <?php foreach ($entries as $entry): ?> <div class='news-column'> A NEWS ENTRY </div> <?php endforeach; ?> </div> I had to also set 'Admin > Setup > Templates > Edit Template: news-index'. Go to URLs tab and check 'Allow page numbers'.
    1 point
  27. Just hook into Page::render or Page::viewable and check the user name against the page name. Sorry, no time for example code, but take a look at the Page Protector module - it should help you with code.
    1 point
  28. @cyberderf Check a field's visibility options under the input tab.
    1 point
  29. Just committed a small update to GitHub which expands the select box if there's only one of it (field add confirmation page):
    1 point
  30. Hello everyone! I've just made my first Processwire module and would like to share it with community. As I did not find any module that displays shots from Dribbble I decided to make my own. I will add default css styles in coming days. I hope someone will find this useful. Feel free to leave any ideas you have how the module can be improved. Thanks!
    1 point
  31. Hi @MaryMatlow, Please read the docs, here (WIP), especially, this section, but for your specific question, this topic . Please note that some newer and amended methods have not yet found their way into the docs, e.g. the method renderRelatedPosts(). However, these are all in this (long, I know) thread but probably best to take a peek at MarkupBlog class itself for all render methods before we get the docs up to speed again.
    1 point
  32. Blog post in Norwegian on setting up https with PW: https://www.asbjornness.no/blogg/https-med-processwire-hos-proisp/
    1 point
  33. your post kinda proves that it is a good idea to hide the label. because in my example it is already hidden that's the original setup: the whole dark line is unnecessary and counterproductive!
    1 point
  34. New version available! It is now possible to choose whether you import your products etc for as much languages as possible, or for only your default language! I also updated the part in the code for making and adding fields to PW.
    1 point
  35. Hi yesjoar, Not sure about the trackChanges as Valery mentioned. But if output formatting is off, then Pw returns an array of images regardless of your max image setting. $p->setOutputFormatting(false); $image = $p->image->first(); $image->description = "Test"; $p->save() $p->setOutputFormatting(true);
    1 point
  36. Hey, The trick is that you have to call trackChange() before changing image/file properties. Here's a piece that works for me: $page_id = '9999'; // set to a real ID $image_field_name = 'images'; $file_name = '10072882.jpg'; $p = $pages->get($page_id); $p->of(false); $img = $p->$image_field_name->get("name=$file_name"); $p->$image_field_name->trackChange("description"); $new_desc = "Surfing bird"; $img->description = $new_desc; $p->save($image_field_name); Hope it works for you too.
    1 point
  37. I think you need something like this (direct page access redirects to the parent page): if ($_SERVER['SCRIPT_URL'] === $page->url) { $session->redirect($page->parent->url); exit; } alternatively, if you would like to show a 404: if ($_SERVER['SCRIPT_URL'] === $page->url) { throw new Wire404Exception(); exit; }
    1 point
  38. When using $ as a char within doublequotes in PHP, (and not to indicating a Variable), it should be escaped with a \ (backslash). When using a $ as char within singlequotes, escaping is not necessary. That is because PHP treats strings in singlequotes 'as is' (no further processing is done on it), whereas strings in doublequotes will be parsed and every found variable get replaced by it's value. So, the above example will work in PHP, but will not provide correct code to work with the javascript in your page! The problem with Diogos example is that it breaks the onClick value. To avoid this you have to use escaped doublequotes for the onclick value and within that value singlequotes (for the string that get passed to the javascript function): echo "<li><a href='#{$child->name}' onClick=\"$.scrollTo( '#{$child->name}', 800 );\">{$child->title}</a></li>";
    1 point
  39. It took me a while but I now have a working example of something that resembles the setup above. I didn't quite get the concept initially that in processwire a page doesn't actually have to be a page, it can just be a data container for my code. Once I got that I managed to put the site together, see code below. Hopefully this will give others a few pointers too. I'm not convinced it's necessarily the best interpretation so it would be great to get advice on this. My homepage code is like this: <?php include("./header.inc"); /** * Homepage template * */ $items = $page->children; foreach($items as $item) echo $item->render(); include("./footer.inc"); ?> As this is a one page website and pages aren't actually physical pages, this allows me to pull in data from child pages of my homepage. My page template looks like this: <div class="page"> <div class="header" id="<?=$page->title?>"> <a name="<?=$page->title?>"></a> <!-- Any content I want in here --> <?php foreach($page->children as $child) echo $child->render(); ?> </div> </div> I wanted to create dynamic navigation. In one page websites the navigation is setup with ID's so the <?=$page->title?> reference allows me to set up whatever page title I want in the backend and have it pulled in as the target for my navigation. Setting up the navigation was fairly straightforward. I based it on Ryan's tutorial here , the code is very similar, I just added href="# and removed the url reference. <ul class="nav"> <?php $root = $pages->get("/"); $children = $root->children(); foreach($children as $child) { echo "<li><a href='#{$child->title}'>{$child->title}</a></li>"; } ?> </ul> I did run into a small problem as I'm using jquery's scrollTo plugin on the links. My original code looks like this and the jquery breaks most likely due to conflict with the php. I originally had this in my footer scripts and changed it over, can't quite remember why off the top of my head but there was a good reason from memory. I also need to get the "active" class working. Any idea how to rewrite/handle this? <ul class="nav"> <li class="active"><a href="#page1" onClick="$.scrollTo( '#page1', 800 );">Home</a></li> <li><a href="#page2" onClick="$.scrollTo( '#page2', 800 );">Page 2</a></li> <li><a href="#page3" onClick="$.scrollTo( '#page3', 800 );">Page 3</a></li> </ul> Moving back to my page template I have the line <?php foreach($page->children as $child) echo $child->render(); ?> This allows me to pull my module code blocks into any page just by assigning a module template to the child page. The structure is the same as my first post but here's where it gets slightly complicated. My modules most of the time span the full width of the page however I also have a few cases where a module just becomes a simple div container and smaller sized code blocks/widgets are positioned within the module itself. It looks something like this: Header Page1 Module1 Submodule 1 (1/3rd width of container) Submodule 2 (2/3rd width of container) Module2 Page2 Footer The above is just an example but I could have 3 submodules within a module block. As they can be in any combination and position it wouldn't make sense to write all the possible combinations in a module block. At the minute to solve this I have a module container with the same php line that's in my page template to pull any submodule content into the module block. While this works I'm not convinced this is the best solution because from the users point of view they have to navigate through the page hierarchy to edit specific blocks rather than all the blocks relative to a page being on that page in the backend. I know I could call in the module templates to my page template with php but that's not very friendly from an admin point of view because it requires editing the main page template each time the module structure needs changed. What's really needed is a way of hiding the module/submodule child pages from the user and pulling all the blocks into their parent page for editing in the backend. Any advice would be greatly appreciated.
    1 point
  40. You can always reset your password just by pasting this temporarily into any one of your templates, and then viewing a page that uses the template: $u = $users->get('admin'); // or whatever your username is $u->of(false); $u->pass = 'your-new-password'; $u->save();
    1 point
×
×
  • Create New...