Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 02/25/2016 in all areas

  1. After convincing my main client/boss of the advantages of PW over WP, I'm currently build his personal/company site new version. He's a Project Management expert and currently works for the United Nations. His website received around 2k unique visitors per day. Running WP on a Digital Ocean 4GB droplet with Varnish and Apache on Ubuntu 14. MySQL DB runs on another droplet with 2GB. There are other apps running on the same 4G server. I'm planning to use Laravel's Forge to admin the new version. It will make things easier I think. This new version will merge two websites, ricardo-vargas.com and macrosolutions.com.br (the company services). I'm posting the screenshots for the template and admin pages of a consulting service that today leaves at: http://macrosolutions.com.br/consulting/projects-offices-assessment-optimization-and-restructing/ on the old site. There's no front-end yet but I reckon posting these screens may help someone. Numbers: 43 Fields organized in 4 tabs.
    9 points
  2. ProDrafts version 2 is now available for download in the ProDrafts board. This one includes the "Live Preview" capability shown in that video above. It also includes "View Both" capability, and several other improvements.
    4 points
  3. Hi guys, I have just released an update to version 3.2.2 on Github. It fixes the security issue with the CHMOD, the problem with many files and has a better detection of changes to files. Sorry that it took so long. But we currently have a lot to do. The module will continue maintained. AIOM4 is on the to-do list. Best regards, David
    4 points
  4. I received an email from Mandrill today which talked about upcoming changes. Here is a link to their Blog entry http://blog.mailchimp.com/important-changes-to-mandrill/
    3 points
  5. Line 713 typo: $_timespamp private static function _getCacheName($files, $prefix = 'css_', $ext = '.css') { // ------------------------------------------------------------------------ // Initialize timestamp variable. // ------------------------------------------------------------------------ $_timestamp = ''; // ------------------------------------------------------------------------ // Calculate timestamp of all files // ------------------------------------------------------------------------ foreach ($files as $file) { $_timestamp = ($_timespamp + $file['last_modified']); } // ------------------------------------------------------------------------ // Create a unique MD5 file name with the specified prefix. // ------------------------------------------------------------------------ return (self::$developmentMode !== true) ? $prefix.md5($_timestamp).$ext : $prefix.md5($_timestamp).'_dev'.$ext; }
    3 points
  6. How about such a syntax? I think this would be flexible enough for any kind of tagging structure. // Get me the tags, // which start with "Tech_", // are used in the tags field of "templates=posts, date>today" // and sort them by number of occurences (maybe named count) $pages->find("template=tag, title^=Tech_, in.tags=[templates=posts, date>today], sort=occurences"); // Not limiting to upcoming posts or even posts $pages->find("template=tag, title^=Tech_, in.tags=[*], sort=occurences");
    3 points
  7. Hi @karnage, welcome to the forums! I don't have time to be specific now, but wanted to point you to this module from Adrian http://modules.processwire.com/modules/admin-restrict-branch/ I think it does what you want.
    2 points
  8. Perhaps rather than initially redirecting them to the login page, you could simply add a login form to the page itself. You could do this manually in your template file, or make use of ProtectedMode (http://modules.processwire.com/modules/protected-mode/), either as is, or maybe you could lift some code to make something custom.
    2 points
  9. I'd suggest just adding a new field to the language template (show system templates in the template list) and putting the iso codes there. Then you can just do $language->iso or similar. That's nothing that should depend on any settings on the homepage. Also there's $language->isDefault() if you need to change any logic only for the default language.
    2 points
  10. I use it to send marketing campaigns using Sendy. Works flawlessly, not complicated to set up, but not the easiest one either. Didn't test it using PW's api yet. SES is very cheap, my client used to pay $100-200 on Campaign Monitor and now pay less than $5. Thanks! I'll take a look on Mail Gun too. I heard about SendGrid, 12k free/month.
    2 points
  11. That would have to be done with Ajax. If you're using jQuery try something like this: $(".MarkupPagerNav a").on("click", function() { $("#container").load( $(this).attr("href") + " #content" ); }); Where the markup would be something like: <div id="container"> <div id="content"> <!--list and pagination go here--> </div> </div> I'm including the pagination on the loaded content, so you don't have to update its state manually with JS. But you can leave it out of the container and update the active link to the one you just pressed in that moment also.
    2 points
  12. Damn it. Saw the news this morning too. A good alternative might be Mail Gun. One of my clients uses it for quite a serious piece of their signup and customer communications. First 10,000 emails are free too.
    2 points
  13. A couple of relevant posts: https://processwire.com/talk/topic/691-wireinput-only-allows-one-dimensional-arrays-why/ https://processwire.com/talk/topic/7867-input-and-associative-array-issue/ From Ryan:
    2 points
  14. I enthusiastically approve of this feature request
    2 points
  15. This module lets you restrict users to a certain branch of the page tree - it can limit editing permissions, as well as the page list view to this branch. http://modules.processwire.com/modules/admin-restrict-branch/ https://github.com/adrianbj/AdminRestrictBranch Restricted View Non-restricted View Note that this module does not add permissions (unlike how PageEditPerUser and PageEditPerRole work), so the user must have template level permissions to edit the pages in the restricted branch. What this does allow though is giving all users/roles editing access for the home template and allowing that to inherit all the way through the page tree and let this module restrict to specific branches. As you can see from the screenshots you can specify how to determine the branch to restrict the user to - either via a matched role name, or via a dedicated page select field on the user's profile. The match role name works like this - if you have a series of branches called: Branch One, Branch Two, etc, users with a role named: branch-one will only have access to Branch One. You can also decide whether to restrict page tree viewing as well and editing privileges (default) or just editing privileges. The Branch Exclusions option is important for things like external PageTable parent branches etc. Main module config settings User specific branch setting on user profile page This module came out of my personal needs as well as this discussion: https://processwire.com/talk/topic/11428-project-design-main-shop-hundreds-of-affiliates/ As always, feedback is very welcome.
    1 point
  16. Today I want to share a little module that adds 2 additional save buttons with redirect and 1 unpublish button to the page edit. 2 additional save buttons: My intention was that it would be nice if someone saves an article in the backend and will be redirected after saving directly to the frontend page of the article. This module adds 1additional save button at the bottom next to the default save button and 1 at the top. So you can choose if you want to save the article with the default save button or you will save it with the custom save button and you will get redirected to the frontend article. 1 unpublish button: The idea behind this was that I want to disable the setting tab for non superuser. The problem was if I hide it, then non superusers are no longer able to unpublish an article. Therefore this module adds an additional unpublish button at the bottom - the user clicks it and the page will be saved with status unpublished. All pages under the admin section will not be affected of this module. Module is multilingual, so you can set the button texts in all languages. Top view page status published: Bottom view page status published: Bottom view page status unpublished: Here is the code: <?php /** * Adding 2 additional save buttons with redirect to frontend and 1 unpublish button for page edit form. * * ProcessWire 2.x * Copyright (C) 2010 by Ryan Cramer * Licensed under GNU/GPL v2, see LICENSE.TXT * * http://www.processwire.com * http://www.ryancramer.com * */ class CustomPageSaveAndUnpublish 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' => 'Custom page save and unpublish module', 'version' => 1, 'summary' => 'Example for adding 2 additional save buttons with redirect and 1 unpublish button to page edit', 'href' => 'http://www.processwire.com', '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->addHookAfter("ProcessPageEdit::buildForm", $this, "addSaveButton"); $this->addHookAfter("ProcessPageEdit::buildForm", $this, "addUnpublishButton"); // tell processwire that this is a page save if ($this->input->post->submit_save_minor) { $this->input->post->submit_save = 1; // attach hook on page save $this->addHookAfter("Pages::saved", $this, "hookPageSave"); } if ($this->input->post->submit_unpublish) { $this->input->post->submit_save = 1; // attach hook on page save $this->addHookAfter("Pages::saveReady", $this, "hookPageSaveReadyUnpublish"); } } public function hookPageSave($event) { //function to redirect to the frontend after save $page = $event->arguments("page"); if ($this->input->post->submit_save_minor) { // this will get saved after this saveReady hook so no need to save here $pageid = $page->id; $goto = wire("pages")->get("id=$pageid")->url; //get url of frontend article wire("session")->redirect($goto); } } public function hookPageSaveReadyUnpublish($event) { //function to change the status to unpublished $page = $event->arguments("page"); $status = $page->status; $unpublishmessage = __("Status of the page is set to unpublished"); if ($this->input->post->submit_unpublish) { if ($status == 1) { $page->status = "2049"; $this->message($unpublishmessage); } } } public function addSaveButton($event) { //function to add the 2 additional save button with redirect at the top and at the bottom $page = $event->object->getPage(); $status = $page->status; if (($page->rootParent->id != "2") AND ($status == 1)) { //dont show on all pages which are under the admin section and which are not published $form = $event->return; $buttontext = __("Save and go to page"); // new submit button $f = $f2 = $this->modules->InputfieldSubmit; $f->attr("name", "submit_save_minor"); $f->attr("value", $buttontext); $f2->attr("name", "submit_save_minor"); $f2->attr("value", $buttontext); $f2->class .= ' ui-priority-secondary head_button_clone'; // add submit button after the regular save button only if page is published $form->insertAfter($f, $form->get("submit_save")); $form->insertAfter($f2, $form->get("submit_save")); } } public function addUnpublishButton($event) { //function to add the unpublish button at the bottom if page has status published $page = $event->object->getPage(); if ($page->rootParent->id != 2) { //dont show on all pages which are under the admin and dont show the button under the delete tab $form = $event->return; $unpublishbuttontext = __("Unpublish"); // new submit button $f = $this->modules->InputfieldSubmit; $f->attr("name", "submit_unpublish"); $f->attr("value", $unpublishbuttontext); // add unpublish button after the save button if ($page->status == 1) { $form->insertAfter($f, $form->get("submit_save")); } } } } Everybody who is interested can download the modul here: CustomPageSaveAndUnpublish.zip Best regards Jürgen
    1 point
  17. In the last few weeks I've notices some request (e.g. here and here) to be able to get pages based on if they are selected in page fields of other pages. I think adding a method for this would be a nice addition to ProcessWire, as it's often the case that the pages itself are options we just want to get, if they are used somewhere. Currently the task "Get all tags used by some blogposts" has to be done manually like this: $tags = $pages->find("template=tags"); foreach($tags as $tag){ // Filter unavailable if(! $pages->count("template=posts, tags=$tag") ) continue; // Do stuff with it } Now it would be nice to have something like this, where we don't need to have a selector for tags (this is done by the pagefield already). // Find all pages, which are selected in the "tags" field of the selected posts $available_tags = $pages->findSelectedPages("template=posts", "tags"); I'm not that big a MySQL guy, but I can imagine this not only improving readability, but also reducing database calls.
    1 point
  18. You don't need regex. You can test simply by converting the string to uppercase and then compare it with the original string: if (strtoupper($str) === $str) EDIT: Or in Js if (string.toUpperCase() === string)
    1 point
  19. Depends a bit on the actual use-case / scenario. If it's a typical article comments feature, I'd say have an admin review the comments before publishing. A JS or PHP solution is probably not going to work in 100% of all cases - if someone lists capitalized terms / company names like IBM, HTML, BMW or some such - that's not necessarily shouting or spam, but valid input. ucwords() would certainly not be the perfect cure; I only ever use it for (english language) titles. For german or french, that would be useless even for titles / headings, because it's not formatted like in english... If that's a real problem, I'd probably look into some regex magic and block form submission, if >x% of the entire text is uppercase, but I'm by no means a regex guru Perhaps something simple as that might help: var str = "OH HAI. HOW ARE YOU TODAY? WOULD YOU LIKE SOME cheese with THAT?", uc = str.replace(/[^A-Z]/g, "").length, total = str.length; if(uc > (total/20)) { console.log("HEY COWBOY! WE'RE NOT IN KANSAS ANYMORE!"); // form submit false etc. }
    1 point
  20. @Pete true that, sadly getting payment from Overseas is another issue, though customers are loving PW, i use them for Projects where customers want strong ownership over content management, however my eager to migrate to 3.0 due to Namespacing and using 3rd Party lib easily.
    1 point
  21. Actually, you might want to look at PageProtector (http://modules.processwire.com/modules/page-protector/) instead. It let's you control access to just specific pages and also lets you embed the login form into your template so the login form sits within the existing look of your page.
    1 point
  22. @Vayu_Robins: +1 for adrians module. That's the perfect fit for your needs. How could I not think of it? I use it myself on a site.
    1 point
  23. Of course, completely forgot! Obrigado Sérgio! I actually prefer to return false for this: $(".MarkupPagerNav a").on('click', function() { $("#container").load( $(this).attr("href") + " #content" ); return false; }); Besides being slightly simpler, it also prevents propagation. Not that it matters that much in this case, but it makes sense to me to use preventDefault() only in the specific cases when i want to keep the propagation working and stopPropagation() in the opposite case. Anyway, good catch! The code wouldn't work without it.
    1 point
  24. That is awesome and just what I needed! Thanks very much for the solution!
    1 point
  25. I think I got it http://stackoverflow.com/questions/9373023/how-can-i-get-a-summary-string-around-a-search-query-within-a-longer-string Thanks!
    1 point
  26. I saw it and changed it after. The $homepage is defined in my _init.php.
    1 point
  27. @LostKobrakai suggestion is better, but if you decided to not add the field to the language page, the previous code will be: <?php // handle output of 'hreflang' link tags for multi-language // this is good to do for SEO in helping search engines understand // what languages your site is presented in foreach($languages as $language) { // if this page is not viewable in the language, skip it if(!$page->viewable($language)) continue; // get the http URL for this page in the given language $url = $page->localHttpUrl($language); // hreflang code for language uses language name from homepage $hreflang = $pages->get('/')->getLanguageValue($language, 'name'); if ( $language->isDefault() ) $hreflang = 'en'; // output the <link> tag: note that this assumes your language names are the same as required by hreflang. echo "\n\t<link rel='alternate' hreflang='$hreflang' href='$url' />"; } ?>
    1 point
  28. Just a small correction, prevent default click behavior: $(".MarkupPagerNav a").on('click', function(event) { event.preventDefault(); $("#container").load( $(this).attr("href") + " #content" ); });
    1 point
  29. Thanks for pointing to the typos. I corrected it.
    1 point
  30. Afaik wireRenderFile does just do a "extract($vars)" to populate the local variables. There's no need to sanitize or otherwise limit data input.
    1 point
  31. Thanks Steve, I've fixed the problem in version 3.2.3. It was late at night. The update is available on Github.
    1 point
  32. Free gogs hosting for open source projects is offered by https://notabug.org/
    1 point
  33. Aah, I see. That's a cool usage of the module you got there! . Using wireRenderFile() keeps the module's input clean, circumvents limit of text allowed in that field plus makes the module much more versatile. One can do all sorts of flexible includes from within the file rendered by wireRenderFile(), depending on the context. I have tested and it works fine here creating a new page (see below). Cloning a page on the other hand leads to a cyclical error (or memory issue) and crashes Apache. In details tab of this module I have: return wireRenderFile('test'); In /site/templates/test.php $out =''; $f = $modules->get("InputfieldText"); $f->label = "Copy Title";// @note: doesn't seem to work $f->attr('id+name','name'); $f->required = 1;// @note: -ditto- $out= $f->render(); // append the field to the form // oh a submit button! $f = $modules->get("InputfieldSubmit"); $f->attr("value","Create Copy"); $f->attr("id+name","createcustomcopy"); $out .= $f->render(); $currentPage = ''; $process = wire('process'); if($process && $process->className() == 'ProcessPageEdit') $currentPage = $process->getPage(); if(!$currentPage) return; echo $out; // let's create a copy $copy = $input->post->createcustomcopy; $title = $sanitizer->text($input->post->name); if($copy) { if(!$title) { $this->error('You need to specify a title for the copied page!'); return; } $p = new Page(); $p->template = $templates->get($currentPage->template); $p->parent = $currentPage->parent; $p->title = $title; //sanitize and convert to a URL friendly page name $p->name = $sanitizer->pageName($p->title); //check if name already taken within same parent. if the same name exist, don't create a new copy // @note; without this line pages were being created in duplicates if($p->parent->child("name={$p->name}, include=all")->id) return; else { $p->save(); $this->message('Created a copy of the page with the title: ' . $title); } }
    1 point
  34. It is probably because it's used by a small fraction of businesses. Way under 1%. It's not a big enough name yet for it to appear in many job ads I think. But one day... The job ads that would be applicable for someone who knows ProcessWire would be the ones that either don't list a preferred CMS at all, or if they list a CMS they put "or similar" - I've seen plenty of those. "WP or similar" which is your opening to go to an interview and open their eyes to the endless possibilities and lack of security flaws (in ProcessWire, in case you thought I was talking about the other one ). I think that dev agencies looking for new staff tend to ask here, as that's far more useful. We've seen it happen a few times before, and that's only the ones we hear about on the forums.
    1 point
  35. Hi all It's been long overdue, but I have approved all pending profiles (well, except one where they were just trying to advertise some database app that had nothing to do with ProcessWire whatsoever!). @rick - it would be nice to do this. I will add it to my list of things to do. Just today I added a manual link in the Dev Directory admin to check the user's "sites using PW" against isit.pw to save me some time so I can certainly see the benefit of automated checks for existing members in the directory too. Can you let me know if that user's website link is still broken please? @incognito.ms - apologies, I was way behind on directory approvals and your profile has now been approved. @Sephiroth - think of it this way, you have the Nigerian market all to yourself then at the moment There are more planned updates to the directory in coming months, and I appreciate everyone taking the time to submit so many sites for verification. I would suggest you all list your sites in the Sites Directory as I can see one or two that aren't there. I appreciate this isn't always possible due to client confidentiality though, but more exposure for your skills where possible can't be a bad thing
    1 point
  36. I don't share the warm fuzzy feelings I get when I use people's modules nearly often enough, so I just left a comment on the module directory page. The short version is that it's saving me from having to create custom modules for a lot of places where I'd want to output some custom, processed output when editing a page and it is streamlining some of the steps I need to perform when approving entries in the dev directory, so thanks for this!
    1 point
  37. Here a small and simple trick to add an option like what asked Kuba2/Jakob. We are going to add a new option to renderPosts(). Steps are : 1) Open the file MarkupBlog.module located under site/modules/ProcessBlog/MarkupBlog.module 2) Add the option 'post_href_in_title' Find the line : //default options for various aspects of posts and add the new following entry to the $defaultOptions array : 'post_href_in_title' => true, // if 'post_href_in_title' = true then post's title will contain a link. If false, only the post's title will be show 3) Find : $out .= "<$h class='post-headline'><a href='{$page->url}'>{$page->title}</a></$h>"; replace to : $out .= $options['post_href_in_title'] ? "<$h class='post-headline'><a href='{$page->url}'>{$page->title}</a></$h>" : "<$h class='post-headline'>{$page->title}</$h>"; We are done for the new option. Then, to render the post without a link in post's title, use now the renderPosts() with the option 'post_href_in_title' set to false : [...] //Render limited number of posts on Blog Home Page $content .= $blog->renderPosts("limit=$limit", false, array('post_href_in_title' => false)); [...]
    1 point
  38. A small contribution: Add an option to have ability to use Self-Signed Certificate on a given SMTP server with WireMailSmtp and PHP >= 5.6 What PHP say - source : https://secure.php.net/manual/en/migration56.openssl.php HOWTO: ----------- 1) In file smtp.php, class smtp_class, we add a member variable and a small function : /* Allow self signed certificate */ var $smtp_certificate = false; Function AllowSelfSignedCertificate($allow = false) { $version=explode(".",function_exists("phpversion") ? phpversion() : "3.0.7"); $php_version=intval($version[0])*1000000+intval($version[1])*1000+intval($version[2]); if($php_version<5006000) return; if($allow) { stream_context_set_option($this->connection, 'ssl', 'verify_peer', false); stream_context_set_option($this->connection, 'ssl', 'allow_self_signed', true); } else { stream_context_set_option($this->connection, 'ssl', 'verify_peer', true); stream_context_set_option($this->connection, 'ssl', 'allow_self_signed', false); } } and, in the Connect() method, call the function just in before we check for the result of stream_socket_enable_crypto : Find : $this->OutputDebug('Starting TLS cryptograpic protocol'); if(!($success = stream_socket_enable_crypto($this->connection, 1, STREAM_CRYPTO_METHOD_TLS_CLIENT))) Replace to $this->OutputDebug('Starting TLS cryptograpic protocol'); $this->AllowSelfSignedCertificate($this->smtp_certificate); if(!($success = stream_socket_enable_crypto($this->connection, 1, STREAM_CRYPTO_METHOD_TLS_CLIENT)) 2) In the file smtp_message.php, class smtp_message_class, add a member variable : /* Allow Self Signed Certificate */ var $smtp_certificate = 0; In the method StartSendingMessage() , assign the new member variable: $this->smtp->smtp_certificate = $this->smtp_certificate; 3) In the file WireMailSmtpAdaptator, class hnsmtp, add a member variable : private $smtp_certificate = false; and in the method set_var_val(), add a case smtp_certificate for our checkbox : Find : case 'smtp_ssl': case 'smtp_start_tls': case 'smtp_debug': case 'smtp_html_debug': Replace : case 'smtp_certificate': case 'smtp_ssl': case 'smtp_start_tls': case 'smtp_debug': case 'smtp_html_debug': In the class constructor, add : $this->emailMessage->smtp_certificate = $this->smtp_certificate; 4) In the WireMailSmtpConfig.php file, add a field : add : $field = $modules->get('InputfieldCheckbox'); $field->attr('name', 'smtp_certificate'); $field->label = __('PHP >= 5.6 - Allow self signed certificate'); $field->attr('value', $data['smtp_certificate']); $field->attr('checked', $data['smtp_certificate'] ? 'checked' : ''); $fieldset->add($field); 5) In the WireMailSmtp.module file, add a settings to the getDefaultdata() : Find : 'valid_recipients' => '' // email addresses of valid recipients. String that we convert to array at runtime. Add after (take care of comma ','): 'smtp_certificate' => 0 // allow or not self signed certificate (PHP >= 5.6) Result : Hope it help. Sorry for my english
    1 point
  39. I must admit i dont know that much about encryption myself, so I have used the following example with a little modification. http://stackoverflow.com/questions/16600708/how-do-you-encrypt-and-decrypt-a-php-string/16606352#16606352 Do not use BLOWFISH and EBC (this it too predictable) as in the example, instead of that i'm using RIJNDAEL_128 (or 256 if you like) and CBC I also recommend to use a long encryption key, maybe something above 1024 characters, or even 2048 long function encrypt($pure_string, $encryption_key) { $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $encrypted_string = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_CBC, $iv); return strtr(base64_encode($iv.$encrypted_string), '+/=', '-_.'); } function decrypt($encrypted_string, $encryption_key) { $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $encrypted_string_dec = base64_decode(strtr($encrypted_string, '-_.', '+/=')); $iv_dec = substr($encrypted_string_dec, 0, $iv_size); $decrypted_string = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $encryption_key, substr($encrypted_string_dec, $iv_size), MCRYPT_MODE_CBC, $iv_dec); return trim(utf8_decode($decrypted_string)); } update: The base64 encode/decode i threw in so that it should be possible to use the encrypted strings as url segments and so are able to use it together with procache
    1 point
  40. In addition, when using https, make sure that your connection is using a strong protocol version and cipher suite. Reference: https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet
    1 point
  41. It's been more than 9 months since I wrote in this thread about our intranet. Well, things happened that had me away for a good while, and when I got back to it, the wishlist exploded. Finally, though, the migrated intranet is up and running, and based on the feedback I'm getting, I can already call it a success. Here's a short feature list: Running on Windows Server 2012R2 / IIS 8.5 A little over 8000 pages, two languages, 600+ frontend users in 15 countries, 45 editors About 20 templates 15 custom modules Reduced custom CRM module code to less than one-eighth (counted in bytes, not lines) Integrated web server authentication and detailed Group permissions using Apeisa's UserGroups module (big thanks there! Keeping our group-based permissions was one of the main requirements for the new CMS) Live user + groups synchronization from Active Directory Granular search via OpenSearchServer (including permissions handling and indexing linked PageFiles) Tag based in-text translation system through custom Textformatter module linked to our ERP database, with own CKEdtior plugin (think detailed technical data sheets where you don't want to edit every language version separately) About 400 dynamic pages that range from simple database-driven lists to rich single page apps Persistent page links using page IDs that get replaced on save + render Versioning for textareas Custom links in the style of "article:CUSTOM_UNIQUE_FIELD" used to fetch recurring content into pages in our in-house manuals Booking system for our inhouse training center using just pages, standard fields and a bit (well, a good bit) of frontend-editing glue, with graphical interactive calendar Pages can be published per language through a multilanguage checkbox, with corresponding indicator icons and actions in ProcessPageList Notice board system (title, short body, optional attachment, expiry date) for main and department pages, with frontend adding/editing and admin interface Detailed permissions reports in backend and through command line for compliance audits Not yet implemented, but a working prototype is already on the test system: a simple question/linear response forum system with rating, tagging, answer accepting and highlighting options, primarily targeted towards international knowledge exchange Big thanks to Ryan, PW is really an outstanding system in terms of flexibility, scaling and ease of integration, and also to everyone who contributed in any way to PW itself or its huge module repository. As a funny side node, I talked to a colleague from manufacturing when migration was still under way, and he was initially a bit miffed that I'd swap the system he already knows (hey, it's only been 7 1/2 years!) - but only until I told him I'd use PW. At the mention of the word "Process" he immediately determined that his workflow to add content would get a lot smoother, something I could confirm without thinking. (The old system had a separation between categories and articles, so you had to create both in different backend screens to get a navigation entry for a simple page that shows just some text - in PW he only needs to tick the "Show in Navigation" checkbox for his new page.) Shows that the right naming choice already gets you halfway to the goal Now that "The Big Project" is done, I'll only have to weather the usual end-of-year-craziness, then I'll get my custom modules into a shape where I can share them (meaning: polish documentation, add reasonable defaults and switch to module config fields instead of config files).
    1 point
  42. The source is on GitHub, knock yourself out https://github.com/mindplay-dk/SystemMigrations
    1 point
  43. Hi Ryan, any plans in the near future with the notifications module? I plan to use it for simple (ajax) user notifications in the frontend. So I would build a process module and some JS code to use ajax user notifications based on SystemNotifications. $user->notifications Regards
    1 point
  44. I'm building a series of Process Modules for internal business functions. We have several processes that require complex forms. More than would be feasible to create using pages. So I decided to use FormBuilder to allow the appropriate users create and maintain the forms. There would be way too many fields required to send all these forms to pages using the built-in FormBuilder process. These are all lengthy forms (and this is a University), so think 10+ forms — some with up to 60 fields. Rather than save the form to a page, we hook into 'FormBuilderProcessor::saveForm' and create a page that references FormBuilder entry. (The page title is the same as the form entry, for example 1.817) I got a few tips from Ryan on that part. There is one base module called "ProcessAdminForms" that has all the common functionality. The modules that extend it can get as specific as needed. The screenshots below are from the "ProcessAdminIPIFs" module. It is an internal HR process that is required to hire a new employee or setup a new vendor. List of entries Show/hide columns (state saved per user via cookie) Viewing an entry Administrative comments & notifications
    1 point
×
×
  • Create New...