Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 03/25/2018 in all areas

  1. Hello All, I started with Joomla on this CMS parade. Then later I put my hands on Wordpress and eventually settled into Concrete 5. Recently I came to know about ProcessWire CMS, while I was looking for a better replacement for Concrete 5 in terms of robust, easiness, compact. I went through few Video tutorials of PW and read the documentation. The installation of PW was smoothy. The concept of Page is awsome. I like the relation of Page, Fields & Templates. There are many things I can equal to Concrete 5 from ProcessWire, yet PW offers a tiny minimal, code level approach for CMS. We have full control over design & data. There are some pitfalls I felt such no sitewide settings, global logo setup etc but it is easily tackled with some API codes. PW api seems amazing, it is par with what Concrete 5 Offers. I have done a simple website in ProcessWire now and going to do a lot further : http://insignnia.in/
    11 points
  2. Welcome to Processwire! I inherited a club website built in Concrete 5, and it was so slow that page loads were taking over 20 seconds. The way the site had been structured wasn't particularly intuitive either. I'm not sure if it was a Concrete 5 issue or poor implementation, but after I converted it to Processwire, I had a dramatic improvement in page load times, and found the page editing was far more intuitive to the point I could hand over day-to-day editing to non-technical users, whereas the previous webmaster, even with several years using the system and some technical knowledge, still ended up making mistakes on Concrete 5. Processwire passed my '1/2 hour test', ie by looking at the documentation for no more than 1/2 an hour, I was able to have enough of an understanding of the system to start customising sites. As a developer, a 2 minute install is nice, but if it then takes hours to understand the structure of the system to start customisation, then it's not great.
    6 points
  3. Dear @horst, thanks for the valuable feedback. Indeed you mentioned a very good point. I suspect I had a slightly different than usual understanding of how to remove image variations created by modules. The current implementation uses a glob (/{page folder}/{original file basename}.*) to delete variations. I'll update the module to use the standard naming scheme — this will have its benefits especially in edge cases, e.g. images will then still get removed if the module is uninstalled or deactivated. Also good idea about having a public method removeOptimizedVariations(). That will be very easy to implement with the previous issue.
    4 points
  4. Welcome to PW and congrats on a lovely site!
    4 points
  5. https://processwire.com/videos/ You can also do a Google search of "Processwire Videos" for other associated links. Welcome to the ProcessWIre Forums. You may want to visit the following link to answer many other questions you may have: https://processwire.com/docs/tutorials/
    3 points
  6. Your website looks great! For sitewide settings, you can simply use a page which is not listed/published or: http://modules.processwire.com/modules/process-general-settings/ http://modules.processwire.com/modules/textformatter-multi-value/ EDIT: In my last project, I've simply added a fieldset with settings fields in it to the bottom of the home (root) page. Then get values from anywhere like: $pages->get(1)->site_name; //"home" is always 1
    3 points
  7. Hi @kaba86 as @dragan mentioned you can simply add another foreach loop to check another level down. I would defiantly check out some tutorials on using processwire to get yourself kickstarted in the right direction and theres lots of quality tutorials not to mention some of my own. https://processwire.com/docs/tutorials/ <?php $children = $pages->get('/')->children; foreach($children as $child){ $class = ""; if($page->id == $child->id){ $class = " current"; } if($child->id == $page->parent->id){ $class = " parent"; } // echo nav links echo '<a name="'.$child->title.'" class="ajax-link'.$class.'" href="'. $child->url .'">'. $child->title . '</a>'; // new code below $childChildren = $child->children; foreach($childChildren as $subChild){ $class = ""; if($page->id == $subChild->id){ $class = " current"; } if($child->id == $page->parent->id){ $class = " parent"; } echo "<div class='sub-item'>"; echo '<a name="'.$subChild->title.'" class="ajax-link'.$class.'" href="'. $subChild->url .'">'. $subChild->title . '</a>'; echo "</div>"; } } ?> The above is not optimised or elegent - just off the top of my head. I seem to remember one of the default themes has a funciton in it's _func.php file that gives you a nest page list given a page varible (and optional max depth) so you could use that too. Hope that helps (also please post you website when its done
    3 points
  8. Hi @d'Hinnisdaël, many thanks for this well crafted module. I (only) have read the modules code and checked some, (maybe critical) points for image modules . Everything seems to be well done! Only one thing I spotted, needs a bit clarification from you, as I may not see the whole picture yet. You added a new hook delete to Pageimage. I cannot see how this integrates with PW's methods for deleting variations. How gets it invoked when I a) delete an image via UI and b) when I call removeVariations() via the API? Or what is it for, exactly? Besides the integration with unlink & removeVariations, it may be very useful to have a function that only removes the variations from ImageOptim! TL;DR
    3 points
  9. I don't know how @benbyf structured his site, i.e. neither the tutorial or the GitHub ReadMe mention any of that. Why don't you just ask him? Personally, I would also tend to use page reference fields to create categories. Together with URL-segments (and maybe altering the JS a bit for the AJAX stuff and history.js functionality) this would be my choice of how to set up such a site. Looking at that code block above, it seems like you just need to check if $child has children (check for one more level deeper), and do some if/else stuff...
    2 points
  10. This module adds a "SEO" tab to every page where you can define a special title, description, keywords, etc. Try it http://aluminum-j4f.lightningpw.com/processwire/ Name: demo Pass: demo123 How to use You can choose between include automatically or use the following methods: $config->seo // includes all the default values and configuration settings // e.g.: $config->seo->title $config->seo->keywords $page->seo // includes all the default values mixed with the page related seo data // e.g.: $page->seo->title $page->seo->keywords // for rendering: $page->seo->render . . Screenshot Download You can download it in the modules repository: http://modules.processwire.com/modules/markup-seo/
    1 point
  11. Not sure where the best place for this is, but I felt like sharing a little snippet for site/ready.php I wrote that creates a PageArray::groupBy method: <?php /** * * Adds a groupBy method to all PageArray instances. * * Returns a nested array, with the values of the page properties whose names * were passed as arguments as the keys. * * Usage: * ====== * * $grouped = $mypagearray->groupBy(field1 [, field2 ...] [, mutator_function]); * or * $grouped = $mypagearray->groupBy(mutator_function); * * Example: * ======== * * $mypagearray = $pages->find("template=blog-post, sort=year, sort=month"); * $grouped = $mypagearray->groupBy("year", "month"); * * foreach($grouped as $year => $monthgroup) { * echo "<div class='year'><h2>$year</h2>" . PHP_EOL; * echo "\t<ul class='month'>" . PHP_EOL; * * foreach($monthgroup as $month => $mypages) { * echo "\t\t<li><h3>$month</h3>" . PHP_EOL; * * echo "\t\t\t<ul class='post'>" . PHP_EOL; * * foreach($mypages as $post) { * echo "\t\t\t\t<li><a href='{$post->url}'>{$post->title}</a></li>" . PHP_EOL; * } * * echo "\t\t\t</ul>\n" . PHP_EOL; * echo "\t\t</li>\n" . PHP_EOL; * } * * echo "\t</li>" . PHP_EOL; * echo "</ul>" . PHP_EOL; * } * * Example Output: * =============== * * <div class='year'><h2>2016</h2> * <ul class='month'> * <li><h3>1</h3> * <ul class='post'> * <li><a href='/grouptest/grouptest-10/grouptest-10-10/'>Group Test 10 10</a></li> * <li><a href='/grouptest/grouptest-6/grouptest-6-10/'>Group Test 6 10</a></li> * <li><a href='/grouptest/grouptest-10/grouptest-10-12/'>Group Test 10 12</a></li> * <li><a href='/grouptest/grouptest-1/grouptest-1-12/'>Group Test 1 12</a></li> * <li><a href='/grouptest/grouptest-5/grouptest-5-3/'>Group Test 5 3</a></li> * <li><a href='/grouptest/grouptest-10/grouptest-10-4/'>Group Test 10 4</a></li> * <li><a href='/grouptest/grouptest-3/'>Group Test 3</a></li> * <li><a href='/grouptest/grouptest-6/grouptest-6-4/'>Group Test 6 4</a></li> * <li><a href='/grouptest/grouptest-10/grouptest-10-7/'>Group Test 10 7</a></li> * </ul> * * </li> * * <li><h3>2</h3> * <ul class='post'> * <li><a href='/grouptest/grouptest-5/grouptest-5-10/'>Group Test 5 10</a></li> * <li><a href='/grouptest/grouptest-3/grouptest-3-7/'>Group Test 3 7</a></li> * <li><a href='/grouptest/grouptest-9/grouptest-9-5/'>Group Test 9 5</a></li> * <li><a href='/grouptest/grouptest-7/grouptest-7-12/'>Group Test 7 12</a></li> * <li><a href='/grouptest/grouptest-3/grouptest-3-11/'>Group Test 3 11</a></li> * <li><a href='/grouptest/grouptest-9/grouptest-9-11/'>Group Test 9 11</a></li> * </ul> * * </li> * * <li><h3>3</h3> * <ul class='post'> * <li><a href='/grouptest/grouptest-7/grouptest-7-10/'>Group Test 7 10</a></li> * <li><a href='/grouptest/grouptest-12/grouptest-12-12/'>Group Test 12 12</a></li> * <li><a href='/grouptest/grouptest-11/grouptest-11-5/'>Group Test 11 5</a></li> * </ul> * * </li> * * <li><h3>4</h3> * <ul class='post'> * <li><a href='/grouptest/grouptest-8/grouptest-8-3/'>Group Test 8 3</a></li> * <li><a href='/grouptest/grouptest-12/grouptest-12-6/'>Group Test 12 6</a></li> * </ul> * * </li> * * </li> * </ul> * * IMPORTANT! * ========== * * Your PageArray needs to be sorted by the fields you group by, or your return array will be an * unorderly mess (the grouping is still correct, but the order of keys is arbitrary). * * Mutator Function: * ================= * * Instead of just reading properties from the page, you can also pass a mutator function * to groupBy. It gets passed the page object as its first arguments and any optional property * names after that. * * This might come in handy if you want to group by year and month but only have a single * DateTime field. You can then use a grouping function like this: * * $blogposts = $pages->find("template=blog-post, sort=created"); * $grouped = $blogposts->groupBy(function($pg) { * return array(strftime('%Y', $pg->created), strftime('%m', $pg->created)); * }); * */ wire()->addHook("PageArray::groupBy", function(HookEvent $event) { $out = array(); $args = $event->arguments(); if(count($args) == 0) throw new InvalidArgumentException("Missing arguments for function PageArray::groupBy, at least 1 required!"); $last = count($args) - 1; $fnc = is_string($args[$last]) ? FALSE : array_pop($args); foreach($event->object as $pg) { if($fnc) { $props = call_user_func_array($fnc, array_merge(array($pg), $args)); } else { $props = array_map(function($propname) use($pg) { return $pg->{$propname}; }, $args); } $cur = &$out; foreach($props as $prop) { if(!isset($cur[$prop])) $cur[$prop] = array(); $cur = &$cur[$prop]; } $cur[] = $pg; } $event->return = $out; });
    1 point
  12. So I decided to wade into module development and created a wrapper module around ImageOptim, a service that compresses and optimizes images in the cloud. ImageOptim currently handles JPG, PNG and GIF files and, depending on the settings you use, shaves off between 15% and 60% in filesize. Great for bandwidth and great for users, especially on mobile. This module handles the part of uploading images to ImageOptim via their official API, downloading the optimized version and storing it alongside the original image. Download & Info GitHub / Module directory / Readme / Usage Why ImageOptim? There are other image optimization services out there, some of them free, that have outstanding ProcessWire modules. A few things make ImageOptim the best tool for most of my customers: It's not free, i.e. it will probably be around for a while and offers support. However, it's cheaper than some of the bigger competitors like Cloudinary. And it does PNG compression better than any of the free services out there, especially those with alpha channels. Installation Install the module like any other ProcessWire module, by either copying the folder into your modules folder or installing it via the admin. See above for downloads links on GitHub and in the module directory. Requirements To be able to upload images to the service, allow_url_fopen must be set on the server. The module will abort installation if that's not the case. I have only tested the module on ProcessWire 3.x installations. I don't see why it shouldn't work in 2.x, if anyone wants to try it out and report back. ImageOptim account To compress images, you first need to sign up for an ImageOptim account. They offer free trials to try the service. Usage (manual optimization) Images can be optimized by calling the optimize() method on any image. You can pass an options array to set ImageOptim API parameters. $image->size(800,600)->optimize()->url $image->optimize(['quality' => 'low', 'dpr' => 2]) // Set quality to low and enable hi-dpi mode Automatic optimization The module also has an automatic mode that optimizes all image variations after resizing. This is the recommended way to use this module since it leaves the original image uncompressed, but optimizes all derivative images. $image->size(800,600)->url // nothing to do here; image is optimized automatically To change compression setting for single images, you can pass an options array along with the standard ImageResizer options. Passing false disables optimization. $image->size(800, 600, ['optimize' => 'medium']) $image->size(800, 600, ['optimize' => ['quality' => 'low', 'dpr' => 2]]) $image->size(800, 600, ['optimize' => false]) For detailed usage instructions and all API parameters, see the usage instructions on GitHub. Filenames Optimized images will be suffixed, e.g. image.jpg becomes image.optim.jpg. You can configure the suffix in the module settings. Roadmap Asynchronous processing. Not really high on the list. Image variations need to be created anyway, so waiting a few seconds longer on first load is preferable to adding complexity to achieve async optimization. Optimize image variations created by other modules. CroppableImage comes to mind. I don't use any of these, so if somebody wants to help out and submit a pull request — all for it! Add a dedicated page in the setup menu with a dashboard and detailed statistics. ImageOptim's API is very barebones for now, so not sure if that's feasible or even necessary. Stability I've been using this module on production sites for some time now, without hiccups. If you do notice oddities, feel free to comment here or investigate and submit PRs.
    1 point
  13. If you're looking to do an elaborate a page builder with ProcessWire and don't want to pull your hair out, I highly recommended viewing this video: A couple notes: with the css grid specification, you can assign multiple blocks to the same grid-area but they will overlap each other. I've "overcome" this by combining multiple blocks into a parent div and assigning that instead. pretty easy to do. i didn't demonstrate it, if your blocks have a grid structure within them (like built with flexbox), you can still assign that block to a grid-area. so if your blocks themselves have a grid structure, that's ok. for example, if your css grid layout is 6 columns, but you have a block that has a grid inside of it (built with like uikit's grid that's 5 columns), you can assign that block to the grid-area. with the css grid specification, the flow of the blocks does not have to match the flow of the grid-areas. this is insanely powerful. Enjoy.
    1 point
  14. Thank you theo for your suggestions. I shall check them out for sure
    1 point
  15. I've got a dashboard app that uses Hubspot API to pull client info for a given domain name. I can share this with you. Our usage is very vertical but it will give you some sort of a start.
    1 point
  16. I suggest just hiding the controls with some custom CSS in the admin (you can add this with Admin On Steroids or Admin Custom Files). That way it's easier to update the core without losing your customisations. One approach is to intercept and modify images in CKEditor fields using a textformatter. Take a look at Image Interceptor.
    1 point
  17. Thank you for your response monchu, I will give it a try. Still, if someone would like to help me out with code, would be really nice. Here is the code of the menu from the Artist profile. <?php $children = $pages->get('/')->children; foreach($children as $child){ $class = ""; if($page->id == $child->id){ $class = " current"; } if($child->id == $page->parent->id){ $class = " parent"; } // echo nav links echo '<a name="'.$child->title.'" class="ajax-link'.$class.'" href="'. $child->url .'">'. $child->title .'</a>'; } ?> Thank you
    1 point
  18. @Juergen Thanks for the shared custom mystyles.js . I was wondering what else I could add to the editor to make the life of my friend easier when adding his content and found quite a few useful ideas even though my project is under Bootstrap but not uikit yet (the last one is in a process of learning )
    1 point
  19. THANK you @dadish — this; SPA + PW as an API + GraphQL for PW, for me is a milestone exciting proposition. I hope I make it the biggest thing to happen to my PW world since I read the word "ProcessWire" on the bottom generous Marty Walker's web site and first visited processwire.com. First steps for me are reading up on PWAs and finally trying to finish a Wes Bos course on ES6, then I'm off to add in PW as an API & GraphQL. Exciting!
    1 point
  20. Hi, I'm toying with the idea of having a central place in PW's translation system for phrases and strings that are frequently used throughout several template files. The way I understand PWs translation system after reading the docs (http://processwire.com/api/multi-language-support/code-i18n/) is that everytime a __('translate-me') is used in a different .php file, the system will pull that 'translate-me' in a context of the .php file where it is used - so basically all translatable strings of _one_ file at a time are manageable via the (very cool) translation tool in PW's admin interface. So if for example I were to use __('Daytime phone number') in, lets say, the home.php as well as in the login.php and maybe a profile.php, I'd need to translate this three times, right? - A solution given in the docs is using the gettext context, and have this pointing to the first template file where the string was used first, so I only need to translate that template's strings and the other two will "see" their translation threre. So in my fabricated example: //home.php: __('Daytime phone number'); //login.php: __('Daytime phone number','/site/templates/home.php'); //profile.php: __('Daytime phone number','/site/templates/home.php'); So I only need to look for the translations of /site/templates/home.php in the translation tool and the other occurances of that string will be taken care for. This now brings me to the idea of creating a php file in, say, "/site/language/strings.php". So what I can now do (but what feels kind of hacky to me…?), I use all the frequently used strings of my several template files in this "strings.php" file, wrapped in their language functions like __('translate me'). in _init.php or maybe in config.php I store this file's path for the context: $i18lctx = '/site/templates/language/strings.php'; And now I can use the transalatable strings in several template/php files like this // in home.php, in archive.php etc __('Hello pilgrim',$i18lctx); In PWs admin interface I'll have all the strings in one place: the strings.php (?textdomain=site--templates--language--strings-php). Is this the right way to go about it or am I overlooking a basic fact (maybe like, dude, this is what the language packs are for)? Cheers, Tom
    1 point
  21. @mscore if you think this should be included in the core module, you should send an issue or feature request at Github, to get better recognition! And many thanks for sharing this solution!
    1 point
  22. The ProcessDashboards module which is the latest iteration of this is back to being a simple helper module, close to the original Dashboard module by @Pete, but with some additional features, and that the module no longer changes anything in the admin, meaning that it doesn't auto-change the admin page to use the process; instead you create one or more dashboards, and input the path to a php file to render the dashboard; if you want to use one of them as the admin home screen, then you just change that admin page's process to use this module (ProcessDashboards). Since making dashboards is fundamentally creating markup, it is better to keep all of the files for the dashboard in the templates folder. Also, if there were to be any dashboard module that output markup, it could become difficult to support multiple admin themes. Users of UIKit theme could build a simple dashboard using all native UIKit markup and not have to include a css framework (as i have done for the examples, which run inside the reno theme). Since this type of setup is not really suitable for a standalone module, or a site profile, i see it more as a construction kit. You need the base module; if you want to use the shortcuts and widgets functionality, there is another module that installs all of the fields & templates for that setup; You need the files that generate the dashboard(s) and the widgets that go in the templates folder, including css/js, libraries, widget partials, and functions. Hopefully this can all be on GitHub soon, once i sort out some issues with my current dev computer (old os no longer being able to connect to github)...
    1 point
  23. For quick study how to structure your pages and menus, try first Blog Profile You don't have to locate each article under category page. From Blog Profile you can learn how to use Page Reference field for category purpose.
    1 point
  24. I'm very happy you like it @alan. You definitely can use this for any single page application. That's exactly why I built this module for. Please don't hesitate to share the issues that might come up when using this module. I would love hear some feedback and maybe fix bugs if there are any.
    1 point
  25. Wow o_O @dadish I am humbled by your excellent work here. I stumbled on this thread researching PWAs and then was transfixed for the full 37 minutes of your excellent video intro. Thank you very much indeed for all of this, I am yet again thankful for the ProcessWire community's generous and excellent work. I've had Vue.js noted down as "something I want to use", along with using ProcessWire as/via an API, and most recently, PWAs. I am hoping, if I've not misunderstood, now I may be able to use all these together for a project. Brilliant! \o/
    1 point
  26. Really, really nice! What do you think of packing this into a fieldtype? Would be nice to have all the logic, files and fields packed into a module and to only have to add your field in the template editor I'm also working on a site with matrix content builder and using field rendering makes the code very clean: My matrix field is called "content" and all my items are included via WireRenderfile(). Then it's as easy as placing a file with the markup in /templates/matrix (here 2columnlayout.php).
    1 point
  27. The grid-template-areas field might want to sport a monospace font for better alignment of those single letter area names
    1 point
  28. This is awesome, @Jonathan Lahijani!!! Great work!! For those eager to learn CSS Grid, I recommend this excellent (and free) course by Web Bos: https://cssgrid.io
    1 point
  29. I too was wondering how to best approach this, as I needed a base configuration that sped up the design layout for each template a client requested. I just spent too much time on this than anything else. Because I am a one man show, and this isn't my primary job, I finally think I found a happy medium, using the following: A combination of using: One main template which is used to build any layout Repeater Matrix Fields as html blocks/containers, which build html code based on the UIKit v2 framework (grid classes, subslasses, etc...) I tried to code in a function which uses the recent Item Depth settings for a Repeater Matrix field to know when to open and close div elements with levels of code blocks, but couldn't quite get it right, as my math and coding skills aren't that great yet, but if anyone manages to get something like this working, it would be great! So instead I just created a bloated if else statement, but I still use the item depth feature to see how the blocks of code would be indented for easy readability within the backend. Backend templates for each widget, so I can add configurations and settings to each particular widget, and a way I could call this from a page reference field A 'Page Reference' field to select which widgets I wanted to show in these containers. A 'Selector' field to target which pages these particular html blocks/containers should be visible. I would love have this in some kind of installable module, but I'm just not skilled enough/don't have the time I hope though that this has given someone an idea of how you can use the above combination to take the hassle out of building page layouts, without touching the front-end code continually I have attached a screenshot to make it a bit clearer on what I am doing... (or trying to do!)...
    1 point
  30. Brain dumping here, but on one end of the spectrum, we have good-ole' templates, which is what ProcessWire is all about. Then on the other end, we have these infinitely configurable, drag-and-drop page builders. Popular ones include: webflow.com (arguably the most elaborate) grapesjs (looks like open-source webflow clone that they encourage CMS's to integrate) yootheme pro (a wordpress builder; Yootheme is the company that makes UIkit, so their approach particularly appeals to me since I'm all in on UIkit); it's interesting to see how a pure, truly inspired uikit builder would be imagined, and yootheme pro is it other wordpress builders: gutenberg, divi, beaver builder, + a million others Of course, if you have a site that has highly relational data and templates, PW is perfect, but then there's those one-off pages, or sections within templated pages, that need the flexibility of a builder so the non-coder editor who's editing the page can do what he needs to do. I think these builders need to take the end-user into consideration... with too much flexibility and an editor without a strong understanding of how they work, it's more likely the resulting builder page that has been created is going to be sub-par. The images might be way too big, the fonts may be off, spacing, etc. etc. Honestly, even when I as a web developer use those builders, it doesn't feel right, but perhaps that's because I'm totally biased. I feel having a strong set of components/blocks that each have a bit of flexibility to them via various options is the better way to go if it makes sense for a site. RepeaterMatrix does this perfectly and because it's through RepeaterMatrix, you can use PW's API to query things if need be. The trade-off is doing column layouts is a bit trickier (not impossible), it's not 100% visual/drag-and-drop, and you have to create a defined list of blocks/components/matrix-types (which is another way of setting up some expectations of what is and isn't possible).
    1 point
  31. The correct word is all times, I haven't come across any site builder that allows 100% control over content without creating a mess or even without the need for code, the closest so far I can think of is October CMS which generates a templates from the frontend and allows you to tweak them, but it requires knowledge of Twig or blade (not sure), really this is an important topic you raised, I have a client i tried convincing to try Processwire, but the client wasn't interested in coding and wanted to builder to achieve all their needs. The only thing i can think of is a Builder 100% built around Processwire API(s) meaning, when they create a Page and add content and use modules from builder, at the backend it should replicate the same process like creating a template, downloading the modules but that will be a very difficult task to achieve. However I would be happy to hear what ideas you have and we can research further upon that. so far Processwire is the best CMS platform that's minimal and straight forward but for developers more. ImpressPages comes close to what you have in mind, I will keep an eye on this thread and contribute should i have more information. If this can be achieved I think we can further push PW to clients and have them replace WordPress, at the same time we should be careful we don't create another WordPress in this ecosystem. what do you think ?
    1 point
  32. Hi @adrianmak You can achieve this by using hooks and my ReCaptcha module. First install the MarkupGoogleReCaptcha module then in file ready.php, write the following code : /* * replace the LAST occurence of $search by $replace in $subject */ function str_lreplace($search, $replace, $subject) { return preg_replace('~(.*)' . preg_quote($search, '~') . '~', '$1' . $replace, $subject, 1); } /* * replace the FIRST occurence of $search by $replace in $subject */ function str_freplace($search, $replace, $subject) { $from = '/'.preg_quote($search, '/').'/'; return preg_replace($from, $replace, $subject, 1); } $captchamod = wire('modules')->get("MarkupGoogleRecaptcha"); wire()->addHookProperty('Page::captcha', function($event) use ($captchamod) { $event->return = $captchamod; }); wire()->addHookAfter('Page::render', function($event) { $template = $event->object->template; $page = $event->object; if ($template == 'admin' && !wire('user')->isLoggedin()) { $captchaScript = $page->captcha->getScript() . '</body>'; $captchaHtml = $page->captcha->render() . '</form>'; $event->return = str_freplace('</form>', $captchaHtml, $event->return); $event->return = str_lreplace('</body>', $captchaScript, $event->return); } }); wire()->addHookAfter('Session::authenticate', function($event) { $page = wire('page'); $template = $page->template; if ($template == 'admin') { if ($page->captcha->verifyResponse() == false) { wire('session')->logout(); wire('session')->redirect(wire('config')->urls->admin); } } });
    1 point
  33. Sounds like you have a good handle on how the process will work, so no reason to worry I think. I've just done something very similar so I can attest that it's quite simple to do in PW. Regarding 1 & 2: most likely you will be querying an API endpoint that will return a JSON string to you. You'll probably find the WireHTTP class useful here - that's what I used. The getJSON() method will convert the JSON response into an associative array that contains all the data you requested. Tracy Debugger will be useful for exploring this array. Then you will use some part of the data as a unique identifier (you could use the title string but there's probably some kind of reference code that will be a better candidate) and based on whether you can find an existing page with that identifier you will either create a new page or update an existing page. Then it's simply a matter of matching items in the array to fields on your page and saving the page at the end. You can use a lazy cron function to automatically query the API endpoint every 24 hours. To delete pages that are no longer contained in the JSON response you can collect all of the unique identifiers in the response and then use a PW selector to get pages not matching any of those identifiers. Those pages you delete.
    1 point
  34. And one more: function n($singular, $plural, $count) { echo t(_n($singular, $plural, $count)); } This handles translations of singular/plural nouns, using the earlier introduced "t" helper. Of course strings have to be listed in "_strings.php" to be translatable in the admin. (I had to use "echo" instead of "return", probably because the template engine I'm using) Usage: n('minute', 'minutes', $page->count_of_something) Using "/*!" instead of "/**" will prevent addition of stars when hitting new lines in IDEs: /*! Intentionally commented out GENERAL _x('minute', 'General'); _x('minutes', 'General'); SEARCH _x('Search site', 'Search'); _x('No matches', 'Search'); *******************************************/
    1 point
  35. tpr's solution is better than the one I posted. To take it a step further, those _x() functions never even need to execute. They can simply be contained in a PHP comment, as they only need to be visible to the language parser, which parses the files directly and doesn't execute the with PHP. So you could do this: /******************************************* Intentionally commented out ​// Search_x('Search site', 'Search'); _x('No matches', 'Search'); // Forms _x('From', 'Forms'); _x('From email', 'Forms'); _x('To', 'Forms'); ... *******************************************/ Of course the actual t() function should not be commented out though.
    1 point
  36. I'm using almost the same setup, but my "t" function handles context too. The good thing is that _strings.php can be copied to your next projects too. function t($text, $context = 'General', $textdomain = '/site/templates/_strings.php') { return _x($text, $context, $textdomain); } _strings.php: // Search _x('Search site', 'Search'); _x('No matches', 'Search'); // Forms _x('From', 'Forms'); _x('From email', 'Forms'); _x('To', 'Forms'); ...
    1 point
  37. I use a similar solution to a _strings.php file, and include it from my _init.php file (prependTemplateFile), so that it's available to all templates. But I bundle all the translated values into a new function (which I'll call _t(), but you could name it whatever you want). So you can call upon that _t() function anywhere that you'd call a __() function. For instance, in your /site/templates/_strings.php file... function _t($label) { static $labels = null; if($labels === null) $labels = array( 'Yes' => __('Yes'), 'No' => __('No'), 'Maybe' => __('Maybe'), 'And so on...' => __('And so on...') ); return isset($labels[$label]) ? $labels[$label] : $label; } From there, you can replace any __('label') call with _t('label'). In this manner, you only need to translate your _strings.php file, and all the other template files can use the translated labels. For the cases where you need to translate text that only exists in a particular file, then you'd continue to use the __() function as usual.
    1 point
  38. I think it's just fine using strings.php if it helps you - actually I'm using this right now, the only difference is that I named it "_strings.php", to avoid showing up as a template file. Another simple solution can be found here, making a dedicated page for strings: https://processwire.com/talk/topic/10443-how-to-do-this-global-vars/
    1 point
  39. You might want to start by reading these... http://www.flamingruby.com/blog/anatomy-of-fields-in-processwire/ http://wiki.processwire.com/index.php/Module_Creation http://processwire.com/talk/topic/4420-page-list-migrator/ - not directly related, but gives you some ideas about working with json in PW http://processwire.com/talk/topic/2394-how-to-present-your-module/ http://processwire.com/api/modules/ https://github.com/ryancramerdesign/ProcessHello https://github.com/ryancramerdesign/ProcessWire/blob/master/site-default/modules/Helloworld.module http://processwire.com/talk/topic/4410-storing-lists-in-pw-fields/ - not directly related; storing serialized field data in db... I'm not sure what you mean by "it should support the admin also". If you mean you want a GUI for it in the admin, then you are looking at a Process Module, most likely. I suggest to have a look at some of the code of the available modules as well. As for JSON, you can either use PW's wireEncodeJSON method or PHP's native json_encode. The difference between the two is that PW's removes empty vaues.
    1 point
×
×
  • Create New...