Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 07/27/2016 in all areas

  1. Horst and I would like to announce the release of v1.0.0 of the WireQueue suite of modules. There are now drivers for textfiles, redis and SQLite and the interface has been extended to include the isEmpty(), purgeItems() and getItems() methods. Enjoy!
    10 points
  2. Dynamic Selects Released 27 July 2016 Dynamic Selects is a commercial module that enables the creation of dynamically related/dependent ajax-driven chained dropdown lists (aka cascading selects) for display and storage of multiple types of data. The module can be used both in the front- (display only) and backend (display and storage of data). Setting up Dynamic Selects is very easy. With minimal effort, site developers can set up simple or complex chained selects. By making a selection in a trigger dropdown, via ajax, values are fetched and dynamically populate options in the dependent select. In turn, making a selection in the now populated select triggers the same action further down in a dependent select. The module only uses/stores ID references to selected options in the selects meaning the most current/up-to-date data will always be displayed in the selects. Currently only ProcessWire managed data are supported. If there is enough demand, we may incorporate external data sources (typically JSON). The module consists of 4 modules ProcessDynamicSelects MarkupDynamicSelects FieldtypeDynamicSelects InputfieldDynamicSelects Video Demo: https://youtu.be/wkhx8xQ5ue4 Documentation: http://dynamicselects.kongondo.com/ Shop: https://processwireshop.pw/plugins/dynamic-selects/ Requires: ProcessWire 2.5 or newer and jQuery if using the frontend module (MarkupDynamicSelects) Features Easily create powerful ajax-driven cascading/chained selects/dropdowns Unlimited number of select dropdowns per field Data-mapping made easy thanks to multiple possible combinations of data relationships, triggers and sources Mutlipe data relationships to chose from ID-based data referencing ensures your data values always stay fresh Remote and local caching to speed up data access and reduce ajax-requests to server User-friendly, intuitive and easy to set up IMPORTANT Before using this module in the frontend, you will need to thoroughly read the security section in the documentation.
    7 points
  3. This module allows the default admin - and other users you specify - to login as any other user as defined in the module config. This could be useful for reproducing errors your users can see on websites or during testing, but I would suggest it is used wisely as there are some obvious snooping abilities in using this. Once installed, you can configure the module to be usable by various members of staff other than the default admin account, as well as define which roles or individual users you will be able to login as. After saving the config settings, you will find a page under the Setup menu in the admin called "Switch User". Selecting a user from the list checks via AJAX whether the user has admin access (this is a basic check for the page-edit permission as by default the admin homepage requires page-edit to load the page tree) and will either allow you to redirect to the homepage or back to the admin depending on that check. Download Here Version History 0.0.6 - Initial release
    4 points
  4. Hello, I made this clone of the Ghost Blog System (http://ghost.org) for demo of the Wire Render Pattern as well as a multi language site and menu system. https://github.com/NinjasCL/pw-ghost As always MIT licence.
    4 points
  5. I think an on-demand google pagespeed and gtmetrix page analyzis could be nice panel additions. On "on-demand" I mean they should analyze only on user request (eg. click on a button). Both have APIs but PS requires an api key, maybe gtmetrix too. I know it's a bigger request, I'm just asking whether you have thought about such feature.
    4 points
  6. I think it's a great idea - I have added to my list. In the meantime I have added a new "Custom PHP" panel which lets you return anything you want. which results in: Not very pretty looking I know - I am sure @tpr will have some style suggestions for me This is obviously not the best solution for things like page speed because it won't work with local dev sites, so as I said, I will work on dedicated panels for those, but this still may be helpful until then, and perhaps also for other things. Some other significant recent updates that I haven't mentioned. There are now separate default panel config options for frontend vs backend The User switcher now lets you logout (while maintaining the session and access to the Tracy debug bar). Until recently, you had to switch to a different user before the logout would work properly.
    2 points
  7. I would have been probably use the Raptorize plugin to make it really clear but this will also do
    2 points
  8. Hey @Can, I just ran into some small things myself installing and configuring this module. Since I don't have shell access to the server (yet) I created a workaround. I've created a template and page called "cronjob" so I could trigger the script from an url (www.domainname.com/cronjobs/?key=123). In the template.php I do a simple check on a get variable (key) to prevent people from accessing it on purpose. From there I include: // Skip access since the guest user is loading the script // Perhaps you might want to look into the permission check stuff since you're bootstrapping ProcessWire $options = array('noPermissionCheck' => true); // Load the Module to get the className $linkCheckerModule = $this->modules->getModule("ProcessLinkChecker", $options); // Include Teppo's LinkCrawler require $config->paths->siteModules . $linkCheckerModule->className() . '/LinkCrawler.php'; // Start crawling $crawler = new LinkCrawler(); $crawler->start(); // Stop ProcessWire from executing $this->halt(); This seems to work fine for me. I've got a lot of data. I still get some notices like Array to string conversion in */site/modules/ProcessLinkChecker/LinkCrawler.php on line 335*. I'll look into them tomorrow.
    2 points
  9. I'll see, thanks. I think a confirm (yes-no) dialog would be of more help here. Strictly forbidding to save the page may result in data lost if the upload never finishes (so you can't save the page itself at all).
    2 points
  10. No pressure, but eagerly looking forward to using Batcher in PW3. In PW2 it was my go-to module for quick and easy bulk deletion of pages generated during site testing. Lister Pro can do that too but needs more clicks. Please keep the option of typing a selector too.
    2 points
  11. Out of necessity (that is, my editors having created pages with hundreds of files attached...) I've whipped up a small module that adds a live search box (just plain jQuery hide/show) to file input fields (just for InputfieldFile, not images, and no searching descriptions yet). I've called it InputfieldFileFilter. If anybody wants to give it a try, it can be found at https://github.com/BitPoet/InputfieldFileFilter It's currently running on PW 2.8, though it should be compatible with other versions as well. I'd be happy to get a little feedback if this is worth rolling into a more elaborate module. The module is really only in alpha state right now, so I'd not recommend to put it onto a production system, and it does need quite a bit of testing. InputfieldFile has a lot of js magic attached after all...
    1 point
  12. If I understand right, you will be outputting all the repeaters on the parent page and each of these will include a link to the booking page. Because a repeater item is a page you can use the page ID to identify it. So on your parent page... foreach($page->my_repeater as $repeater_item) { $link = "/booking/?id={$repeater_item->id}"; // output the markup for your repeater item including the link } And on the booking page... $id = $sanitizer->int($input->get('id')); $repeater_item = $pages($id); if($repeater_item->id) { // output the markup for your repeater item } You could use a URL segment instead of a GET variable if you prefer.
    1 point
  13. Hej, maybe $page->repeater->eq()? see: https://processwire.com/api/ref/wire-array/ cheers! Steffen
    1 point
  14. @Pete Back in 2013 @Nico Knoll asked for a "Mark as solved" button for the forums, so user could see which questions are still unsolved, which was a great feature for this forum. Now with the new version this button is missing. Could you please let it return?
    1 point
  15. @Manaus That's great! Here is my hooked method: public function hookInitTwig(HookEvent $event) { $twig = $event->arguments('twig'); $twig->addGlobal('hsaApp', wire('config')->hsaApp); $twig->addGlobal('hsaDist', wire('config')->hsaDist); $twig->addExtension(new \Twig_Extension_Debug()); } The only problem with what you have done is that you have amended the original module. When you update that module, you will lose your added code. If you add to a hooked method outside of the Twig module, your changes will be preserved.
    1 point
  16. Ok finally I got it, I added this line to the initEngine function within TemplateEngineTwig.module: $this->twig->addExtension(new Twig_Extension_Debug()); And now there it is! Thanks!!
    1 point
  17. @Wanze Yep, that was it -- dump() works perfectly now!
    1 point
  18. @Gazley Did you add the dump extension via hook? http://twig.sensiolabs.org/doc/functions/dump.html Even if debug is active in twig, this function needs to be added additionally. Cheers
    1 point
  19. Very interesting template setup with all the params and helpers, @clsource!
    1 point
  20. at least for google it would be as easy as adding a link like this echo '<a href="https://developers.google.com/speed/pagespeed/insights/?url=' . $page->httpUrl . '">Google Speedtest</a>';
    1 point
  21. @bernhard Sure. Provide me with details / login and I will have a look. We can also communicate in german if you like.
    1 point
  22. @jmartsch i'm using it on a project i'm developing at the moment and it works really nicely. I've also built a little module. maybe you are interested in testing/collaboration? at the moment it has only 2 buttons on hover: 1) show the template path that is rendering the item 2) show edit button to edit this item directly of course it is quite similar to fredi and feel... ps: the built in modal has an awesome experience on mobile. its fullscreen and feels almost like a native app
    1 point
  23. ...in addition to the comments above, I am not sure anyone attempted to compare RC to ProcessWire. At least, I don't see this in the OP.
    1 point
  24. @Surikat - perhaps you are just trying to enlighten us all about RedCat and we appreciate that, but it does smell a little like advertising. You should know that ProcessWire is actually a framework first and the optional CMS component is actually built on top of this framework. I know this is not obvious from reading some of the blurbs on the website, but this is one of the main reasons why ProcessWire is so great because you have all the tools from the framework available for your use on the frontend, or to build your own CMS on top of it if you wish.
    1 point
  25. I've updated the module with some small changes. Exceptions are no longer unintentionally catched when using the CLI tool. Also the default migration format does now include seconds in the timestamp. These are optional so migrations without seconds will still work.
    1 point
  26. I can certainly see your intent and I think it's ok that you want to let people know about problems in redactors pricing strategy. But this is not the place to discuss this in more detail than that. This part of the forum is just a loose wish list for ProcessWire, which happened to have a topic about redactor. We're by no means promoting or otherwise suggesting anyone to use redactor and even if this topic convinced you initially to use redactor your problem is not related to us. As I said I support you trying to simply warn other people, but everything else is just not our business.
    1 point
  27. Thought it was high time I released this one into the wild after sitting on it for a year or more - oops!
    1 point
  28. The French example seems to make sense, but as far as I can tell, English versions make more sense when the apostrophe is removed: lets-go vs. let-s-go, havent-been-there vs. haven-t-been-there, adrians-suggestion vs. adrian-s-suggestion, etc. I'd suggest going with Adrian's suggestion above.
    1 point
  29. Can't you add it to the Character Replacements list in the Page Name config settings: /module/edit?name=InputfieldPageName
    1 point
  30. Actually crashed my on-board graphics. And I'm not even joking.
    1 point
  31. You'd create each field separately, so you can "rollback" each field separately, too. Migrations are not bound to "a specific development step" or alike. Just add as many as you need to bring the installation to the state you need. Rollback's are also the way to go if you made some mistakes. Just rollback the migration, change your mistake and rerun it. If you've already shared the migration, or you've already saved data you want to keep, you could also add another migration, which does only correct your mistake, e.g. for your example just set the field limit and save this change.
    1 point
  32. No need for the if statement here: $hero_images = $page->closest("hero_gallery.count>0")->hero_gallery; (Also the count selector is incorrect above)
    1 point
  33. I don't really understand what your page structure is and what you are trying to output. Maybe you could show... the structure of this branch of the page tree what templates are used at each level an example of what you want your output to be ...then it would be easier to help. But generally I think the problem is that you need to get $categ_team_year and $past inside your loop, using $categ. Also, you need to use count() in your if() statements when testing if a PageArray is empty. Maybe something like: $categ_team = $page->children("template=categ_team"); foreach($categ_team as $categ) { $categ_team_year = $categ->children("template=categ_team"); $past = $categ->find("template=member, actual=0"); $content .= "<h2><a href='{$categ->url}'>{$categ->title}</a></h2>"; if(count($categ_team_year)) { foreach($categ_team_year as $year) { // do something with $year } } if(count($past)) { foreach($past as $member) { // do something with $member } } }
    1 point
  34. Just added color significance to PW and Tracy Log panel icons. Red for errors, exception, critical Orange for everything else, including warnings, info, debug, and any custom names PW logs Green for none All colors are based on log entries from the last 5 seconds which should cover everything loaded/redirected etc during the last page load. The idea being that you don't want the red or orange colors to be triggered from an error that was recorded days ago, even if it's the most recent entry. Hopefully this logic makes sense and it provides a useful visual cue to let you know that something was just logged. PS - as part of this I needed a different icon for the Tracy log panel - you'll see it's now burning campfire logs - it's actually hard to find a nice small icon for logs
    1 point
  35. Thank you for the directions. Exactly what I needed. I just re-installed the multi language option. Renamed the default language English (en) to Dutch (nl). Installed a dutch language pack over the old English one. Deleted the German and Finnish pre-installation and I installed French as the second language. Before I forget: I changed the page names on the homepage too (in the settings tab). Except for some minor translations issues that can be fixed, there is no sign of English anymore.
    1 point
  36. you can do it after the install, if you have installed a single language site profile. Most of us have created their personal starter site profile, I think. It has all settings for default language (inkl.language pack), and the modules, one never can miss, etc. To export a site profile is easy with the site profile exporter module.
    1 point
  37. What you have shown there is not the Family tab for the template - it's the Settings tab for the page. The Family tab for Template has two fields that may be relevant to your problem: "Allowed template(s) for children" and "Allowed template(s) for parents". Check the Family tab... for the template of the page you are trying to move and the template of the parent page you are trying to move it under ...and make sure the allowed templates permit the move you are trying to do.
    1 point
  38. Here are a few background links on SmartyPants, if that will be of any help: https://daringfireball.net/projects/smartypants/ https://michelf.ca/projects/php-smartypants/ https://michelf.ca/projects/php-smartypants/typographer/
    1 point
  39. It's not really designed to be used in a template through the API, the use case was to make re-using images and documents in CKEditor less complicated. Behind the scene, MediaLibraries are nothing but pages with a MediaImages and MediaFiles field, the magic is the concise overview over dedicated media pages (and their creation without navigating through the page tree) and, most importantly, the quick selection in the CKEditor dialogs. You can get the available libraries for a page through the API though: /* Retrieve all available MediaLibraries for the current page */ // get possible parents first $mparents = $page->parents->and($page); // get PageArray with all possible libraries $libs = $pages->find("template=MediaLibrary, parent=$mparents"); // do something with libraries foreach($libs as $lib) { echo $lib->title . PHP_EOL; // Every library is just a page with the fields MediaImages and MediaFiles foreach($lib->MediaImages as $img) { echo "<img src='$img->url'/><br/>" . PHP_EOL; } } Of course, you can fetch a specific library through regular selector syntax too, e.g.: $lib = $pages->get("template=MediaLibrary, name=global-media"); foreach($lib->MediaFiles as $file) { // ... }
    1 point
  40. I now solved it like this //search the first viewable child and redirect public function ___execute() { $moduleChildren = $this->page->children; foreach ($moduleChildren as $modulechild) { if ($modulechild->viewable()) { $this->session->redirect($modulechild->url); return; } } }
    1 point
  41. To start out with PW you don't even need to use or understand oop. You just need to understand the api processwire does provide and a basic understanding of using php. You'll learn all the other stuff on the go, which will be much easier with a real use case at your sight.
    1 point
  42. A bit OT, but if you can plan the languages hirarchy right from the start of a new site, you can do it this way: enable languages support set Title / Label of the default language to your desired none english native language, (e.g. 'Deutsch' (German)) drop in the none english language pack (for admin backend) into the default language, (e.g. german langpack) add a new language to it and drop in a language pack for any none english language or simply don't drop in a language pack to get the english version (but not as the default one!) As a nice sideeffect every new user in your system gets the native language per default without have it to select from the list. So, yes, this is no solution if you once have set it up and need to switch the default language afterwards, but just want to note it.
    1 point
  43. Hi 3fingers, I'd try taking AutoDetect language out of the picture at first, just to make sure the other part is working. Maybe try testing using a separate browser, or 'incognito/private browsing' tab, so that you're not logged in or anything. In case it helps, here's full module code I used: <?php class LanguageDefault extends WireData implements Module { /** * getModuleInfo is a module required by all modules to tell ProcessWire about them * * @return array * */ public static function getModuleInfo() { return array( 'title' => 'LanguageDefault', 'version' => 1, 'summary' => 'A work around to changing the default language.', 'href' => 'https://processwire.com/talk/topic/9322-change-default-language-for-homepage/?p=89717', 'singular' => true, 'autoload' => true, ); } /** * Initialize the module * * ProcessWire calls this when the module is loaded. For 'autoload' modules, this will be called * when ProcessWire's API is ready. As a result, this is a good place to attach hooks. * */ public function init() { $this->session->addHookBefore('redirect', $this, 'setDefaultLanguage'); } public function setDefaultLanguage($event) { if ($this->page->id == 1 && $event->arguments(0) == $this->page->localUrl('default')) { $event->arguments(0, $this->page->localUrl('fr')); } } }
    1 point
  44. Hi, Here is what you can do to redirect the home page '/' to the French home page: Set page names for both languages for the home page ('en' for English, 'fr' for French) In the LanguageSupportPageNames settings, choose the option "No - Root URL performs a redirect to: /name/". When you go to the root url '/' it will redirect you to '/en/' Finally, create a module to hook into Session::redirect to force the redirection of the root url to the French translation as follows: public function init() { $this->session->addHookBefore("redirect", function($event) { if ($this->page->id == 1 && $event->arguments(0) == $this->page->localUrl('default')) { $event->arguments(0, $this->page->localUrl('fr')); } }); } The hook checks whether you are viewing the home page, and whether you are redirecting to the English url, and if so, it changes the url to the French url. This solves the problem of the home page. The problem remains if someone has saved a direct link to a page without a language prefix, e.g., '/about/', since this will still be redirected to '/en/about/'.
    1 point
  45. Hi again! Here's my Disqus import script! Some fields doesn't work correctly, but the basic parsing and import works fine. Will update this post as my code improves. Feel free to chip in! EDIT: Updated code, which runs fine now. Just successfully imported +16000 comments <?php # Heavily inspired by: http://www.binarytides.com/disqus-comments-importer-script-in-php/ ini_set('max_execution_time', 0); // unlimited execution time, because of large amount of comments ini_set('memory_limit', '512M'); $file = 'disquscomments.xml'; $doc = new DOMDocument(); $doc->load($file); $thread_list = array(); $threads = $doc->getElementsByTagName('thread'); foreach($threads as $thread) { if (!isset($thread->getElementsByTagName('link')->item(0)->textContent)) continue; $comment = array(); $comment['thread_id'] = $thread->getAttribute('dsq:id'); $comment['url'] = $thread->getElementsByTagName('link')->item(0)->textContent; $path = parse_url($comment['url'], PHP_URL_PATH); $path = preg_replace("/(\/){2,}/", "/", $path); // remove multiple slashes $path = $sanitizer->url($path); if ($pages->get($path)->id){ $comment['page_id'] = $pages->get($path)->id; } $thread_list[$comment['thread_id']] = $comment; } $post_list = array(); $posts = $doc->getElementsByTagName('post'); foreach($posts as $post) { $comment = array(); $comment['comment_id'] = $post->getAttribute('dsq:id'); $comment['thread_id'] = $post->getElementsByTagName('thread')->item(0)->getAttribute('dsq:id'); $comment['comment'] = $post->getElementsByTagName('message')->item(0)->nodeValue; $comment['created_at'] = $post->getElementsByTagName('createdAt')->item(0)->nodeValue; $comment['email'] = $post->getElementsByTagName('author')->item(0)->getElementsByTagName('email')->item(0)->nodeValue; $comment['name'] = $post->getElementsByTagName('author')->item(0)->getElementsByTagName('name')->item(0)->nodeValue; if ($post->getElementsByTagName('parent')->item(0)) { $comment['d_parent_id'] = $post->getElementsByTagName('parent')->item(0)->getAttribute('dsq:id'); } if (isset($thread_list[$comment['thread_id']]) && isset($thread_list[$comment['thread_id']]['page_id'])){ $thread = $thread_list[$comment['thread_id']]; $comment['page_id'] = $thread['page_id']; // the corresponding PW page's ID $post_list[$comment['comment_id']] = $comment; // only accept pages with pageids } } $postsadded = 0; foreach($post_list as $post){ if ($pages->get("disqus_id={$post['comment_id']}")->id) continue; //ignore already imported $c = new Page(); $c->setOutputFormatting(false); $c->template = $templates->get("mycomment"); $c->username = $post['name']; $c->title = "temporary title"; $c->publish_date = $post['created_at']; $c->disqus_id = $post['comment_id']; $c->body = $post['comment']; // If there's a parent comment, use this as parent if (isset($post['d_parent_id']) && isset($post_list[$post['d_parent_id']])){ $disqusparentID = $post_list[$post['d_parent_id']]; $savedParent = $pages->get("disqus_id={$disqusparentID['comment_id']}"); // must find already created page if ($savedParent->id){ $c->parent = $savedParent; } else { $c->parent = $page; // dump it here } } elseif (isset($post['page_id'])){ $c->parent = $post['page_id']; // root comment } else { continue; } $c->save(); $c->name = $c->id; $c->title = $c->id; $c->save(); $postsadded++; } echo "<br>#######STATS#########<br>"; echo "added +{$postsadded} comments<br>"; echo "total of threads in disquscomments.xml: ".$threads->length."<br>"; echo "total of posts in disquscomments.xml: ".$posts->length."<br>"; echo "total of posts imported: ".count($pages->find('template=mycomment'));
    1 point
×
×
  • Create New...