Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 09/20/2017 in all areas

  1. I think if the site works for you with no issues, the dev tag is completely irrelevant. I use the dev branch on a lot of sites that are live, ProcessWire has always been very stable, which is why it is my CMS of choice.
    5 points
  2. https://www.baumrock.com/portfolio/individuelles-crm-und-controlling-tool/ I'm happy to share my biggest and most interesting ProcessWire project so far with you It's a 100% custom office-management solution that helps my client to keep track of all their contacts, projects and finance/controlling stuff. Conception was done back in 2016 and the software is productive since begin of this year. My client is very happy with the result and so am I. Some technical insights: Everything is done inside the PW Admin. I'm using the Reno Theme with some custom colors. In the beginning I was not sure if I should stay with the pw admin or build my own admin-framework but now I'm VERY happy that I went with PW Almost all of my custom Process Pages use my RockDatatables module - there are still some limitations but without it, this project would not have been possible For the charts I used Google Charts and chartjs - both play well together with the datatables and make it possible to display filtered data instantly: also my handsontable module was created for this project to have a nice and quick option for matrix data inputs: Lister and ListerPro were no options as i needed much more flexibility regarding data presentation (like colorization, filtering and building sums of selected rows): invoices are highly customisable as well and easy to create. PDFs are created by php and mPDF by the way: all data is dummy data populated via my Module RockDummyData have a nice weekend everybody
    4 points
  3. New website for the Camel cigarette brand. When you enter you will see an legal smoking age alert in Spanish, please click on the lower right option "Soy mayor de edad, me registraré luego" (Legal age confirmation) https://camel.com.do Modules used: ProCache Croppable Image 3 Form Builder Login for Facebook ProDrafts Profiler Pro ProcessWire API Explorer Tracy Debugger ListerPro Redirects
    4 points
  4. The custom CKE toolbars per role feature starts to get shape (continued from here). I decided not to use roles but selectors instead for more flexibility (restrict by user role, name, email, etc). There is also a field "filter" to restrict customizations to certain fields. The biggest issue was figuring out how one could enter these infos in the admin. A full-fledged click-and-play UI was out of scope so the good old textarea-based solution seemed the best option. Even so it's not the simple key=value situation that I've used in the module a few times. I was about to use JSON but that's hard to write and error-prone so finally I made it with INI format, using parse_ini_string in the code. That worked so well that I will use it in the future for sure. I need to add a way to specify toolbar items to add/remove instead setting them directly, and it'll be ready for consumption
    2 points
  5. You can manually include any file you want. You dont have to use $config->appendTemplateFile. <?php namespace ProcessWire; // home template ?> <div pw-id="content"> this is content </div> <?php include_once 'layouts/my-layout.php'; Only requirement is that the file you include needs to have <!DOCTYPE declaration and <html> tag in it. <?php namespace ProcessWire; // my-layout.php ?> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <main id="content"></main> </body> </html> From the documentation in WireMarkupRegions.php This takes anything output before the opening `<!DOCTYPE` and connects it to the right places * within the `<html>` that comes after it. /** * Identify and populate markup regions in given HTML * * To use this, you must set `$config->useMarkupRegions = true;` in your /site/config.php file. * In the future it may be enabled by default for any templates with text/html content-type. * * This takes anything output before the opening `<!DOCTYPE` and connects it to the right places * within the `<html>` that comes after it. For instance, if there's a `<div id='content'>` in the * document, then a #content element output prior to the doctype will replace it during page render. * This enables one to use delayed output as if it’s direct output. It also makes every HTML element * in the output with an “id” attribute a region that can be populated from any template file. It’s * a good pairing with a `$config->appendTemplateFile` that contains the main markup and region * definitions, though can be used with or without it. * * Beyond replacement of elements, append, prepend, insert before, insert after, and remove are also * supported via “pw-” prefix attributes that you can add. The attributes do not appear in the final output * markup. When performing replacements or modifications to elements, PW will merge the attributes * so that attributes present in the final output are present, plus any that were added by the markup * regions. See the examples for more details. * * Examples * ======== * Below are some examples. Note that “main” is used as an example “id” attribute of an element that * appears in the main document markup, and the examples below focus on manipulating it. The examples * assume there is a `<div id=main>` in the _main.php file (appendTemplateFile), and the lines in the * examples would be output from a template file, which manipulates what would ultimately be output * when the page is rendered. * * In the examples, a “pw-id” or “data-pw-id” attribute may be used instead of an “id” attribute, when * or if preferred. In addition, any “pw-” attribute may be specified as a “data-pw-” attribute if you * prefer it. * ~~~~~~ * Replacing and removing elements * * <div id='main'>This replaces the #main div and merges any attributes</div> * <div pw-replace='main'>This does the same as above</div> * <div id='main' pw-replace>This does the same as above</div> * <div pw-remove='main'>This removes the #main div</div> * <div id='main' pw-remove>This removes the #main div (same as above)</div> * * Prepending and appending elements * * <div id='main' class='pw-prepend'><p>This prepends #main with this p tag</p></div> * <p pw-prepend='main'>This does the same as above</p> * <div id='main' pw-append><p>This appends #main with this p tag</p></div> * <p pw-append='main'>Removes the #main div</p> * * Modifying attributes on an existing element * * <div id='main' class='bar' pw-prepend><p>This prepends #main and adds "bar" class to main</p></div> * <div id='main' class='foo' pw-append><p>This appends #main and adds a "foo" class to #main</p></div> * <div id='main' title='hello' pw-append>Appends #main with this text + adds title attribute to #main</div> * <div id='main' class='-baz' pw-append>Appends #main with this text + removes class “baz” from #main</div> * * Inserting new elements * * <h2 pw-before='main'>This adds an h2 headline with this text before #main</h2> * <footer pw-after='main'><p>This adds a footer element with this text after #main</p></footer> * <div pw-append='main' class='foo'>This appends a div.foo to #main with this text</div> * <div pw-prepend='main' class='bar'>This prepends a div.bar to #main with this text</div> * * ~~~~~~ * * @param string $htmlDocument Document to populate regions to * @param string|array $htmlRegions Markup containing regions (or regions array from a find call) * @param array $options Options to modify behavior: * - `useClassActions` (bool): Allow "pw-*" actions to be specified in class names? Per original/legacy spec. (default=false) * @return int Number of updates made to $htmlDocument * */ public function populate(&$htmlDocument, $htmlRegions, array $options = array()) { ... }
    2 points
  6. You can implement it anyway you like, I was just introducing a few api methods that I use quite often. I like being DRY with my code but with templates, I lean towards using template files and wireRenderFile() function over basic functions if the markup does not include too much logic https://processwire.com/blog/posts/processwire-2.5.2/#new-wirerenderfile-and-wireincludefile-functions Skim over api methods once or twice to see what's available to you, you'll appreciate PW once more. So much good stuff is buried in the docs (and blog posts)
    2 points
  7. That's a great explanation, thanks. Using the new page ref field, I managed to get a counter onto the posts pretty easy too: // category-index.php <ul class="list-unstyled"> <?php $categories = $pages->get("/categories/")->children; $categories->sort("name"); foreach ($categories as $category): // how many items are in returned PageArray $counter = count($category->blogPosts); ?> <?php // if any posts have this category selected, then render it with counter if ($counter): ?> <li class="py-1"> <a href="<?= $category->url; ?>"><?= $category->title; ?> (<?= $counter; ?>)</a> </li> <?php endif; endforeach; ?> </ul> I like this two way relationship stuff! Seem to making progress using PW so much faster than any system I used previously, it's remarkable. Got pretty much everything linking to everything else now: ...and made a little function to output the categories on each post: // _func.php /** * Render blog post categories * * @param PageArray $items * @return string * */ function renderCategories($items) { $arr = []; foreach ($items->categorySelect as $category) { array_push($arr, "<a href='$category->url'>{$category->title}</a>"); } $str = implode(" / ", $arr); if ($arr) { return "Posted in: " . $str; } } used like: // blog-entry.php <p>Posted in: <?= renderCategories($page); ?></p> And: It's the first time I've had such a great time learning a CMS. The positive vibe on this forum is a massive plus to me, keeps me motivated.
    2 points
  8. Maybe how PW checks if the same page is being edited in a different window could be of help? Have a look at the method checkProcessKey() in SystemNotifications module.
    2 points
  9. Wow @bernhard what an impressive work! The developer heart is blooming.
    2 points
  10. Thanks for the reply - you're definitely on the right track there. Your suggestion solves the issue for PW 3.0.62, but when installing PW 3.0.75 I still get the error below: I'm guessing that might be due to this part of FieldtypeRepeater.module firing as soon as PW is bootstrapped, before the module cache has had the chance to clear. Can you see a way to work around that? Edit: this edit to FieldtypeRepeater does the trick... if(!$field->type || $field->type->className() != $className) continue; I have created a GitHub issue for this.
    2 points
  11. I'm not sure around which version but almost all caches were migrated to DB from filesystem. I presume it's faster to access DB as it's cached in the memory than accessing a file on the disk. But inside install.php you can flush module cache by adding $wire->modules->refresh() before the last screen when PW is ready to be bootstrapped. /** * Execution controller * */ public function execute() { // ... if(isset($_POST['step'])) switch($_POST['step']) { case 0: $this->initProfile(); break; case 1: $this->compatibilityCheck(); break; case 2: $this->dbConfig(); break; case 4: $this->dbSaveConfig(); break; case 5: require("./index.php"); /** @var ProcessWire $wire */ // Refresh module cache $wire->modules->refresh(); $this->adminAccountSave($wire); break; default: $this->welcome(); } else $this->welcome(); // ... }
    2 points
  12. Do you want something like this? Moving a page before Admin > Pages? Then try using $pages->insertBefore(), no need to change page status at all. $anchor = $pages(3); // `Pages` page $sortee = $pages(1354); // page to move before `Pages` $pages->insertBefore($sortee, $anchor); <?php /** * Sort one page before another (for pages using manual sort) * * Note that if given $sibling parent is different from `$page` parent, then the `$pages->save()` * method will also be called to perform that movement. * * @param Page $page Page to move/sort * @param Page $sibling Sibling that page will be moved/sorted before * @param bool $after Specify true to make $page move after $sibling instead of before (default=false) * @throws WireException When conditions don't allow page insertions * */ public function insertBefore(Page $page, Page $sibling, $after = false) { /* ... */ } EDIT: Moving before Tree works too $anchor = $pages(8); // `Tree` page $sortee = $pages(1354); // page to move before `Tree` $pages->insertBefore($sortee, $anchor);
    2 points
  13. For more tips, check out this blog post: https://processwire.com/blog/posts/making-efficient-use-of-fields-in-processwire/ Edit: I've written a tutorial about this topic
    2 points
  14. ConnectPageFields Allows the connecting of two related Page fields so that changing one updates the other. Purpose of module An example: suppose your website is about movies. You have a template "movie" with Page field "actors". For each movie you add the actors that appear in the movie. All good, but what if you want to find results like... the 10 actors who have appeared in the most movies actors who haven't appeared in any movies since 1990 You cannot retrieve these pages with a single efficient $pages->find() query, and must load a large PageArray into memory in order to iterate or filter it. For the sake of making these types of queries more efficient you could structure your templates/fields so that movies are added to actors instead, but this may be a less comfortable workflow and can run into equivalent problems (e.g. "find the 10 movies with the largest cast"). The solution is to have a two-way relationship so that movie pages have an "actors" Page field and actor pages have a "movies" Page field. This module will keep these two Page fields in sync so that adding "Ryan Gosling" to "Drive" automatically adds "Drive" to "Ryan Gosling". Also, you can select the same Page field in both Page field A and Page field B. For example, create a "Related" Page field for related pages. Choose "Related" for both fields in a pair in the module config. Now when you add "Orange buffoon" to Related for "Donald Trump", "Donald Trump" is automatically added to Related for "Orange buffoon". Usage Install the ConnectPageFields module. If you haven't already done so, create the two Page fields you want to connect and add them to templates. In the module config select the two Page fields in a "Connected field pair" row as Page field A and Page field B. You can add rows as needed using the "Add another row" button. Troubleshooting Make sure you have set the "Selectable Pages" settings for each Page field correctly: The settings for Page field A should allow pages using the template(s) that Page field B has been added to. The settings for Page field B should allow pages using the template(s) that Page field A has been added to. http://modules.processwire.com/modules/connect-page-fields/ https://github.com/Toutouwai/ConnectPageFields Module config: Demo showing how changing one Page field updates the other:
    1 point
  15. One of PW 3.010's major novelty was the introduction of Horst's new image resizing engine that uses ImageMagick. Now I understand that ImageMagick can convert images to Webp, the image format that Google says can reduce image size up to 34% compared to JPEG. Mozilla is apparently adding support to Firefox, and even the Safari team is playing with it, so it looks like Webp is soon going to be available in most major browsers. If Horst's module can be extended to add Webp conversion, that would be a great addition to PW's already very powerful image manipulation arsenal. I'm currently using the free ImageEngine Lite to serve Webp images to supporting browsers, and the results are impressive. I routinely get images that are between 25 and 60% smaller compared to JPEG, with the same visual quality. I would love to eliminate the need to rely on a third-party service though.
    1 point
  16. Just something I was trying out recently that might be useful to someone... With the following hook added to /site/ready.php you can adjust the CKEditor toolbar that a particular role gets for a particular field. Use the name of your CKEditor field in the hook condition. $this->addHookBefore('Field(name=my_ckeditor_field)::getInputfield', function(HookEvent $event) { $field = $event->object; // Define toolbar for a particular role if($this->user->hasRole('editor')) $field->toolbar = 'Format, Bold, Italic, -, NumberedList, BulletedList, Outdent, Indent'; }); Or what I find useful on some sites is adding extra toolbar buttons for superuser only that you don't trust editors to use. $this->addHookBefore('Field(name=my_ckeditor_field)::getInputfield', function(HookEvent $event) { $field = $event->object; // Add extra buttons for superuser only if($this->user->isSuperuser()) $field->toolbar .= ', Table, TextColor'; }); You could use the same technique to selectively define other CKEditor settings such as 'stylesSet', 'customOptions', 'extraPlugins', etc.
    1 point
  17. 1 point
  18. 1 point
  19. For anyone not following the issues repo: Ryan has committed a fix for this issue to the dev branch.
    1 point
  20. Ryan committed a change back in May in response to this issue but it hasn't been merged to the master branch yet.
    1 point
  21. Let me introduce you: https://processwire.com/blog/posts/introducing-tracy-debugger/
    1 point
  22. Protip: you can filter empty categories and specify sort in your selector, and simplify your code like this <?php namespace ProcessWire; // get categories that have been referenced by a blog post $categories = $pages('template=category, blogPost.count>0, sort=name'); // $categories = $pages('parent=/categories/, blogPosts.count>0'); ?> <?php if ($categories->count): ?> <ul class="list-unstyled"> <?php foreach ($categories as $category): ?> <li class="category"> <a href="<?= $category->url ?>"><?= $category->title ?> (<?= $category->blogPosts->count ?>)</a> </li> <?php endforeach; ?> </ul> <?php else: ?> <p>No categories yet.</p> <?php endif; ?> And using API methods, your post items can be simplified to: <article class="post"> <h1 class="post__title">...</h1> <p class="post__summary">...</p> <p>Posted in: <?= $post->categories->implode('/', function($c){return "<a href='{$c->url}'>{$c->title}</a>";}) ?></p> </article> https://processwire.com/api/ref/wire-array/#pwapi-methods-retrieval https://processwire.com/api/ref/wire-array/implode/
    1 point
  23. Ah, you're quite right - was one of my sites that hasn't upgraded yet (missed it!). Thanks
    1 point
  24. That's right. (you were putting boundaries using selectors though, so, not "all" pages) You're not searching through all pages to check if their template and category matches with your criteria. With page reference fields, all relevant pages are known beforehand (check out field_blogPosts table in your db), and fetched from DB all at once once you call $cat->blogPosts.
    1 point
  25. It works fine inside repeaters too $wire->addHookAfter('InputfieldPage::getSelectablePages', function($event) { if($event->object->hasField == 'pageRef') { $event->return = $event->pages->find('template=repeater_testRepeater, include=all'); } });
    1 point
  26. Ah, I totally missed that. There's a config field that lets you define session timeout. /** * Session expiration seconds * * How many seconds of inactivity before session expires * * @var int * */ $config->sessionExpireSeconds = 86400; That would be tricky to implement and probably not be secure at all. But using $input->whitelist you can keep sending and receiving a session id which can be used to identify a session across browsers. Google "cookieless session php". https://stackoverflow.com/questions/5882401/cookie-less-sessions-in-php https://stackoverflow.com/questions/14229193/sharing-session-between-different-browsers I tried playing with $config->sessionFingerprint, but I couldn't make it work as you asked /** * Use session fingerprint? * * Should login sessions be tied to IP and user agent? * IP fingerprinting may be problematic on dynamic IPs. * Below are the possible values: * * 0 or false: Fingerprint off * 1 or true: Fingerprint on with default/recommended setting (currently 10). * 2: Fingerprint only the remote IP * 4: Fingerprint only the forwarded/client IP (can be spoofed) * 8: Fingerprint only the useragent * 10: Fingerprint the remote IP and useragent (default) * 12: Fingerprint the forwarded/client IP and useragent * 14: Fingerprint the remote IP, forwarded/client IP and useragent (all). * * If using fingerprint in an environment where the user’s * IP address may change during the session, you should * fingerprint only the useragent, or disable fingerprinting. * * If using fingerprint with an AWS load balancer, you should * use one of the options that uses the “client IP” rather than * the “remote IP”, fingerprint only the useragent, or disable * fingerprinting. * * @var int * */ $config->sessionFingerprint = 1;
    1 point
  27. @bernhard This looks amazing! I developed a CRM for a customer using ListerPro with some custom enhancements, but this is another level up! Must have been a LOT of work. Hope you were paid well
    1 point
  28. About as "managed" as the host gets Thanks abdus. I've solved it by copying back all my working files and re-installing the database and it worked.
    1 point
  29. Just visited @apeisa's repo and found that I had forked it just over 5 years ago! (And lodged a pull request at the time.) Good job GitHub has a longer memory than me.
    1 point
  30. This module was suggested by @abdus to me in another post and after giving it a whirl, it's pretty awesome! If you link one way, it makes sense for pages to be linked the other way also.
    1 point
  31. You might be right. initFields() is called from FieldtypeRepeater::init() method, which fires after PW finishes loading modules in boot sequence. You can try deleting module cache directly from the database using the config prepared in the previous step, before PW is bootstrapping. This forces Modules class to recreate caches <?php $db = new \ProcessWire\Database( '127.0.0.1', 'dbUser', 'dbPass', 'dbName', 1234 ); // OR (not tested) $config = new \stdClass(); require_once __DIR__ . '/site/config.php'; // OR $config = \ProcessWire\ProcessWire::buildConfig(__DIR__); $db = new \ProcessWire\Database($config); $db->query("DELETE FROM caches WHERE name = 'Modules.site/modules/'"); But a better solution would be excluding caches table from the exported profile.
    1 point
  32. Thanks for the report @szabesz - I have now overwritten the PHP time limit for these actions, so that should take care of your timeout issues. Regarding the duplicate names problem - I have committed a new version which adds logic to check for duplicate usernames and also checks against users already in the system. This all occurs before it adds any users, so it should make for a much nicer experience. If you have a chance to test, please let me know how it goes. Screenshot showing when duplicates are detected Screenshot showing when existing users are detected
    1 point
  33. I saw this once but I was lazy to make the adjustments will do later
    1 point
  34. Here you go <?php $nutritionMarkup = ''; $i = 0; foreach ($order as $o) { $item = $nutrition->get("name%=$o"); // skip if item or its name or value not populated if (!$item || !$item->name || !$item->value) continue; // increase the counter and assign left or right $class = (($i++) % 2 == 0) ? 'left-box' : 'right-box'; // to place two nutrition values in a wrapper, // open up wrapper before every even item if ($i % 2 === 0) $nutritionMarkup .= "<div class='nutrition-detail'>"; // markup for each nutritional value $nutritionMarkup .= " <div class='$class'> {$item->name}<br> {$item->amount} {$item->unit} </div> "; // close the wrapper after every odd item if ($i % 2 === 1) $nutritionMarkup .= "</div>"; } echo $nutritionMarkup;
    1 point
  35. This is actually so useful that I need to add to AOS (if you don't mind) Removing toolbar items is easy with your code but AOS may add extra buttons via CKEditor plugins. I found out that listing them in "removePlugins" is enough, so this can be used to remove extra plugins with ease: $this->addHookBefore('Field(inputfieldClass=InputfieldCKEditor)::getInputfield', function(HookEvent $event) { // do not show modified data on Field edit page if ($this->wire('process') != 'ProcessPageEdit') { return; } $field = $event->object; if($this->wire('user')->hasRole('editor')) { $field->toolbar = 'Bold, Italic'; $field->removePlugins = 'div, justify'; // plugins to remove $field->formatTags = 'p;h2;h3;h4'; // allowed format tags, separated with semicolon } });
    1 point
  36. Thanks for all the tips. I am aware of limit @mr-fan but thanks anyway. This is just a demo for now but will start writing some real content asap. Looking forward to being able to give something back to the community. Although my guides will probably be nothing new to seasoned users, they will make it easier for people new to PW, or maybe to persuade people choosing a CMS/CMF that PW is super easy to use even for non/beginner coders. Anyway, back from work now so can continue. -EDIT- I added a Datetime field to the blog posts with no output so I can choose the post date on each one rather than use the created date i.e. I can backdate them to make it look like I've been doing this for ages... seriously though, now it shows the two latest posts per category and I can manipulate the dates better (for HTML/CSS output) from the field timestamp. I'll probably stick that in a function as the date will be displayed on multiple templates. // category-index.php <?php namespace ProcessWire; ?> <div class="container"> <div class="row"> <?php $categories = $pages->get("/categories/")->children; foreach ($categories as $category): ?> <div class="col"> <h2><a href="<?= $category->url; ?>"><?= $category->title; ?></a></h2> <ul class="list-unstyled"> <?php $posts = $pages->find("template=blog-entry, categorySelect=$category, sort=-postDate, limit=2"); foreach ($posts as $post): ?> <li><a href="<?= $post->url; ?>"><?= $post->title; ?></a></li> <?= $post->summary; ?> <?php endforeach; ?> </ul> </div> <?php endforeach; ?> </div> </div> Seems to work ok: Thanks for all the help. Maybe my first post should be "How to make a blog with processwire"...
    1 point
  37. Bumped to 0.2.4-beta: Fixes schema changes (per ThePixelDeveloper's recent commits). Note that the sitemap doesn't render using the XML viewer, and it's still to be tested in Search Console. A few changes to ModuleConfig. Adding image fields to the sitemap is now only possible if your site contains image fields. Hook priority is changed (from after to before). This is mostly due to SystemNotifications showing a 404 for the sitemap.xml route. add X-SitemapRetrievedFromCache header for debugging purposes. PS, I'm working on a new docs site as well. It'll be powered by PW, and will have docs for all my modules. On a separate note: Jumplinks is on the mantleshelf for a little while as I'd like to do a refactor to make the code a little more 'lean' and my schedule is not what it once was. There are a few things bugging me with regards to the way it's put together at the moment, and it feels a little chunky. Sorry for the delay on that one, guys...
    1 point
  38. Bumped to 0.2.3-beta: Adds support for ProcessWire 2.8 Rolls back previous fix in favour of the FileCompiler doing its thing
    1 point
  39. Bumped to 0.2.2-beta: Explicitly requires PW 3+ and PHP 5.6+ Fixes a namespace issue that broke install and uninstall routines I'd very much appreciate it if everyone who would like to use MarkupSitemap tests it and provides some feedback. By the looks of it, this can be pushed to stable 1.0.0 soon, unless any other bugs come up... Thanks!
    1 point
  40. @Zeka, that's a different method. That add() is for adding a new page to a specified parent and assigning it a given template. The add() @celfred is referring to is the WireArray method documented here and as seen here. It adds an item to the end of a WireArray (and its derivatives, e.g. PageArray). @celfred It shouldn't add without a save. There's something funky going on in your code. It's hard to pinpoint where because we can't see the original code. Maybe there's some other save or $real is being overwritten somewhere. I've tested your pseudo function and it works as expected in both PW 2.7 and PW 3.0.71. If I pass $real as false, the $page is not added to the Page Field. Btw, though made up, this variable name will throw an error $new-eq
    1 point
  41. @bernhard, I've found a way. Hooking ProcessPageEdit::buildForm works wire()->addHookAfter('ProcessPageEdit::buildForm', function (HookEvent $e) { /** @var ProcessPageEdit $edit */ $templates = ['post', 'basic']; $edit = $e->object; $page = $edit->getPage(); if (!in_array($page->template->name, $templates)) return; /** @var InputfieldForm $form */ $form = $e->return; /** @var InputfieldImage $imageField */ $imageField = $form->children->findOne('name=images'); if (!$imageField) return; $imageField->maxFiles = 1; }); When I try to add more images, field just replaces the first one, not allowing more than one. If there were multiple images before, they disappear after page save, only the first one remains.
    1 point
  42. Let me introduce you to Field - Template Contexts https://processwire.com/videos/field-template-context/ As for the multiple/single image fields, I usually have a single image field that is set to return an array, and use only what I need by getting the first image or filtering with tags. I rarely, if ever need to create a second images or files field. With template contexts, change the description and notes to guide the editor and use it in the templates however you want. You might add some checks with hooks and throw error if someone added more than one image to a template. wire()->addHookBefore('Pages::saveReady', function (HookEvent $e) { $limitedTemplates = ['post', 'event']; // limit to only one image /** @var Page $page */ $page = $e->arguments('page'); if(!in_array($page->template->name, $limitedTemplates)) return; if ($page->images->count > 1) throw new WireException('Only one image is allowed'); });
    1 point
  43. I've just pushed a new version of the Create Users Batcher which adds proper CSV parsing (so you can have commas, quotes, spaces etc in other user fields) - thanks to @Rudy for noting this deficiency. I have also added the option to use JSON instead of CSV in case that is easier for your needs. Creation now also supports image fields so you can use a URL to an image to have that added to the user's page.
    1 point
  44. Each repeater item is a page itself, and repeater field is the parent page that holds these. (You can even see it under Admin>Repeaters). You need to iterate over $page->studioImages to get each set, than iterate over them to get individual images. Here's how: <?php foreach ($page->studioImages as $imgSet): // each repeater item ?> <div class="swiper-slide"> <div class="image-gallery"> <?php foreach ($imgSet->studio as $img): // each image in a repeater item ?> <a href="<?= $img->url ?>"> <div style="background-image: url(<?= $img->url ?>)"></div> </a> <?php endforeach; ?> </div> </div> <?php endforeach; ?>
    1 point
  45. We're developing the site for a Swiss architect, and meanwhile we prepared a very simple temporary page: http://gamisch.ch/ It's powered by PW, so I thought I should post anyway
    1 point
  46. If there are issues with a given module, you can always post your query/questions in the sub-forum for that module: You can also report technical issues/possible bugs with modules directly at the particular Project Page (Github) location: https://github.com/adrianbj/AdminRestrictBranch On the ProcessWIre Modules Page, for each module --- it lists the links to both the Forum Support and Project Page (Github): http://modules.processwire.com/modules/admin-restrict-branch/ I would encourage everyone to use these essential resources to let the module authors know about bugs, possible changes or any other issues with their module. Most module authors are willing to make changes to how things operate based on the comments or queries from module users.
    1 point
  47. @Kiwi Chris Welcome! Could this module be a solution for you? AdminRestrictBranch last update 12.04.2017, stable
    1 point
  48. It's made 100% in PW and sent directly from this server using PW's WireMail interface with either Teppo's WireMailSwiftMailer or Horst's WireMailSMTP.
    1 point
  49. Hi Rodwyn, Welcome to PW forum Hopefully the example below help you out: Deleting $page->of(false); $itemToRemove = $page->Body_Repeater->eq(0); $page->Body_Repeater->remove($itemToRemove); $page->save(); Editing $itemToEdit = $page->Body_Repeater->eq(0); $itemToEdit->of(false); $itemToEdit->body = "My new content"; $itemToEdit->save(); Things you need to remember with Repeater is that Repeater Item is an actual page in processwire but being hidden in the tree and obviously Repeater field is an array of pages (wirearray). For documentation please refer to this page: https://processwire.com/api/arrays/ Hope this helps
    1 point
  50. it is working using ob_end_clean() that erase the output buffer and turn off output buffering ob_end_clean(); $mpdf = new mPDF(); $mpdf->WriteHTML('<p>Your first taste of creating PDF from HTML</p>'); $mpdf->Output(); exit;
    1 point
×
×
  • Create New...