Leaderboard
Popular Content
Showing content with the highest reputation on 11/30/2016 in all areas
-
Hi everyone, Here's a new module that I have been meaning to build for a long time. http://modules.processwire.com/modules/process-admin-actions/ https://github.com/adrianbj/ProcessAdminActions What does it do? Do you have a bunch of admin snippets laying around, or do you recreate from them from scratch every time you need them, or do you try to find where you saw them in the forums, or on the ProcessWire Recipes site? Admin Actions lets you quickly create actions in the admin that you can use over and over and even make available to your site editors (permissions for each action are assigned to roles separately so you have full control over who has access to which actions). Included Actions It comes bundled with several actions and I will be adding more over time (and hopefully I'll get some PRs from you guys too). You can browse and sort and if you have @tpr's Admin on Steroid's datatables filter feature, you can even filter based on the content of all columns. The headliner action included with the module is: PageTable To RepeaterMatrix which fully converts an existing (and populated) PageTable field to either a Repeater or RepeaterMatrix field. This is a huge timesaver if you have an existing site that makes heavy use of PageTable fields and you would like to give the clients the improved interface of RepeaterMatrix. Copy Content To Other Field This action copies the content from one field to another field on all pages that use the selected template. Copy Field Content To Other Page Copies the content from a field on one page to the same field on another page. Copy Repeater Items To Other Page Add the items from a Repeater field on one page to the same field on another page. Copy Table Field Rows To Other Page Add the rows from a Table field on one page to the same field on another page. Create Users Batcher Allows you to batch create users. This module requires the Email New User module and it should be configured to generate a password automatically. Delete Unused Fields Deletes fields that are not used by any templates. Delete Unused Templates Deletes templates that are not used by any pages. Email Batcher Lets you email multiple addresses at once. Field Set Or Search And Replace Set field values, or search and replace text in field values from a filtered selection of pages and fields. FTP Files to Page Add files/images from a folder to a selected page. Page Active Languages Batcher Lets you enable or disable active status of multiple languages on multiple pages at once. Page Manipulator Uses an InputfieldSelector to query pages and then allows batch actions on the matched pages. Page Table To Repeater Matrix Fully converts an existing (and populated) PageTable field to either a Repeater or RepeaterMatrix field. Template Fields Batcher Lets you add or remove multiple fields from multiple templates at once. Template Roles Batcher Lets you add or remove access permissions, for multiple roles and multiple templates at once. User Roles Permissions Batcher Lets you add or remove permissions for multiple roles, or roles for multiple users at once. Creating a New Action If you create a new action that you think others would find useful, please add it to the actions subfolder of this module and submit a PR. If you think it is only useful for you, place it in /site/templates/AdminActions/ so that it doesn't get lost on module updates. A new action file can be as simple as this: <?php namespace ProcessWire; class UnpublishAboutPage extends ProcessAdminActions { protected function executeAction() { $p = $this->pages->get('/about/'); $p->addStatus(Page::statusUnpublished); $p->save(); return true; } } Each action: class must extend "ProcessAdminActions" and the filename must match the class name and end in ".action.php" like: UnpublishAboutPage.action.php the action method must be: executeAction() As you can see there are only a few lines needed to wrap the actual API call, so it's really worth the small extra effort to make an action. Obviously that example action is not very useful. Here is another more useful one that is included with the module. It includes $description, $notes, and $author variables which are used in the module table selector interface. It also makes use of the defineOptions() method which builds the input fields used to gather the required options before running the action. <?php namespace ProcessWire; class DeleteUnusedFields extends ProcessAdminActions { protected $description = 'Deletes fields that are not used by any templates.'; protected $notes = 'Shows a list of unused fields with checkboxes to select those to delete.'; protected $author = 'Adrian Jones'; protected $authorLinks = array( 'pwforum' => '985-adrian', 'pwdirectory' => 'adrian-jones', 'github' => 'adrianbj', ); protected function defineOptions() { $fieldOptions = array(); foreach($this->fields as $field) { if ($field->flags & Field::flagSystem || $field->flags & Field::flagPermanent) continue; if(count($field->getFieldgroups()) === 0) $fieldOptions[$field->id] = $field->label ? $field->label . ' (' . $field->name . ')' : $field->name; } return array( array( 'name' => 'fields', 'label' => 'Fields', 'description' => 'Select the fields you want to delete', 'notes' => 'Note that all fields listed are not used by any templates and should therefore be safe to delete', 'type' => 'checkboxes', 'options' => $fieldOptions, 'required' => true ) ); } protected function executeAction($options) { $count = 0; foreach($options['fields'] as $field) { $f = $this->fields->get($field); $this->fields->delete($f); $count++; } $this->successMessage = $count . ' field' . _n('', 's', $count) . ' ' . _n('was', 'were', $count) . ' successfully deleted'; return true; } } This defineOptions() method builds input fields that look like this: Finally we use $options array in the executeAction() method to get the values entered into those options fields to run the API script to remove the checked fields. There is one additional method that I didn't outline called: checkRequirements() - you can see it in action in the PageTableToRepeaterMatrix action. You can use this to prevent the action from running if certain requirements are not met. At the end of the executeAction() method you can populate $this->successMessage, or $this->failureMessage which will be returned after the action has finished. Populating options via URL parameters You can also populate the option parameters via URL parameters. You should split multiple values with a “|” character. You can either just pre-populate options: http://mysite.dev/processwire/setup/admin-actions/options?action=TemplateFieldsBatcher&templates=29|56&fields=219&addOrRemove=add or you can execute immediately: http://mysite.dev/processwire/setup/admin-actions/execute?action=TemplateFieldsBatcher&templates=29|56&fields=219&addOrRemove=add Note the “options” vs “execute” as the last path before the parameters. Automatic Backup / Restore Before any action is executed, a full database backup is automatically made. You have a few options to run a restore if needed: Follow the Restore link that is presented after an action completes Use the "Restore" submenu: Setup > Admin Actions > Restore Move the restoredb.php file from the /site/assets/cache/AdminActions/ folder to the root of your site and load in the browser Manually restore using the AdminActionsBackup.sql file in the /site/assets/cache/AdminActions/ folder I think all these features make it very easy to create custom admin data manipulation methods that can be shared with others and executed using a simple interface without needing to build a full Process Module custom interface from scratch. I also hope it will reduce the barriers for new ProcessWire users to create custom admin functionality. Please let me know what you think, especially if you have ideas for improving the interface, or the way actions are defined.15 points
-
Welcome to the ProcessWire forums then! You've certainly found the right tool for such a task. As to your questions, you're of course right. Under the hood, it all boils down to MySQL statements, so for a reasonably experienced DBA, sanitizing data and optimizing indexes isn't magical. A lot of the terms and descriptions you've encountered are thus meant for frontend developers or those who aren't able to breathe SQL instead of oxygen The "easier and safer" part means that you should PW's API to access PW's pages and fields, not invent your own SQL to do so when there's a perfectly simple API already in place that sanitizes its selectors and builds the correct JOINs, and if you have means like calling $page->children("rank=".$sanitizer->selectorValue($input->get->rank)) or iterating $page->somepagefield you don't have to worry about someone sneaking a POST or GET value past you that lets them view data not meant for them, nor do you have to worry about accidentally removing valid characters, all the while the code is wonderfully descriptive about what it intends to do. I guess you could go with storing most of the relevant data for your game in custom tables, and as long as you're the only one managing the system, you'll be fine. If, however, things keep growing, you either need someone equally versed in databases (especially if something goes wrong unexpectedly), or you need a good visual representation of your data in the backend - that's where pages come in. Since pages are just DB entries in the "pages" table and their fields associated rows in a field_FIELDNAME table, there's not much overhead but a lot of visible gain. In case something unpredictable happens (like a winner being disqualified afterwards) you can simply go into the backend, open the page for the race, edit the "results" field and remove the participant in question. That's a simplified example, of course (you'll likely use something more elaborate than a simple page field, e.g. a PageTable or Repeater so you can also store the time and perhaps starting slot and completed rounds), but the gist holds true. Being able to see your data at first glance and being able to use the backend to modify and reorder it is the main advantage of using Pages and Fields. Think of pages not just as display interfaces in the frontend, but more as links between your data. A page's template is its data model and the page id the key that links the instance data. A pagefield links to another model's instance. You get all that referential stuff with a nice GUI. There are a few more obvious advantages of pages, like their status flags. Set a page to hidden and it's not listed in $pages->find() calls. Set it to unpublished and it doesn't show up at all. Of course page access can be limited in any number of ways, but to use PWs built-in access system, you need to have pages. There are pages for displaying data, which you'll have anyway, and there are pages only for storing data to be associated with other pages but not to be displayed on their own. Again, don't just think of a single admin scenario. With multiple editors/admins (like customary for a larger CMS) you can for example limit just who can modify these data pages - this might be a lot fewer people than those who can update the pages including their values. Avoiding name clashes is always an issue when you import pages. Each page name under the same parent has to be unique - it's used to build the URL to the page, after all, no matter if the page is accessible through the web or not (yet). The logic for page names and the danger of duplicates differ from case to case, so it's always something you'll have to determine yourself how to deal with. Ryan's approach in the linked topic is ProcessWire's default logic, but if a name already exists, you could also let your import script create a completely different name with a microtime-based timestamp with a fixed prefix so you can find those later and deal with them manually, or you could avoid importing them at all and just log a warning, or you could put in your own logic to create a unique name. In case of races if you might e.g. be normally using location-date as the name pattern, but you might have two races on the same day there and append the race number. Whatever fits your need. I'd suggest you play around a little with field templates / partials. Your site might be a perfect use case for those and explain far better than any prose we write here what the real advantage of using pages and fields for any kind of data can be.8 points
-
UPDATED Thank you to everyone responded. I am closing this post since it's already been fulfilled. ======================================================================== Hi, We are Adnet Inc., a full service web development/hosting/maintenance company from Vancouver, BC. We're looking for contract front-end developer(s) to implement PW sites. PM me to discuss. Cheers, Rudy Affandi rudy@adnetinc.com4 points
-
New website for Fabrica Captial – Commercial Real Estate Investment http://fabrixcap.com/ (previously at http://www.fabricacapital.com/) Design by http://crookdesign.co.uk/3 points
-
I don't know if it's the best practice, but i normally just organize all the files inside the templates folder since it's easier when you import/export site profiles because they get included. My normal file structure looks like this: I place all 3rd party plugins (jquery, bootstrap plugins, etc) under the vendor folder. I also use a somewhat MVC (not strictly) approach, so I place all my controller files in functions folder, and all my views in views folder. You get the idea. I hope this helps.3 points
-
Take a look at this gist: https://gist.github.com/adrianbj/437e3945e9d774f5a67e Also, this thread: You may also want to consider these modules: http://modules.processwire.com/modules/media-library/ https://processwireshop.pw/plugins/media-manager/3 points
-
Whoa, Adrian you rock as usual thanks so much! And the idea of contribution to the actions is the best part of all.3 points
-
It's meant to be, but it's not. Take this one: https://github.com/matjazpotocnik/DynamicRoles Edit on 3. Jan 2018: updated my version of droles with fixes for GH issues 14 and 16.3 points
-
Update: Menu Builder Version 0.1.6. Changelog Fixed a JS issue that stopped 'select all' checkbox from working in Menu Builder dashboard Fixed InputfieldMarkup issue that prevented HTML in description not to be properly rendered. Thanks @Jonathan Lahijani and @Michael van Laar Menu Builder is now PW2.8 + PW3.x compatible! (first one of mine off the blocks!)3 points
-
Announcing that I've tested and can confirm that RuntimeMarkup is compatible with ProcessWire 2.8.x and ProcessWire 3.x2 points
-
You can manually install it, like any other module - just copy the file into your site/modules/ directory, do a modules refresh and click install. You might want to check out @mr-fan' s version in that thread I linked to as I think he extended it to also work with file fields (not just image fields), which you will want for audio clips.2 points
-
Based on my experiences with several thousand images of mine, several thousand images of my customers and many image variations from many sites around the world (from the showcase directory), I can say: The core rendering engines seem to do a pretty good job ! But that are just my experiences.2 points
-
Underscores in host names are invalid according to RFC1132, which allows only letters, digits and hyphens. They are only allowed in DNS names for resource records. So PW is operating in undefined territory.2 points
-
2 points
-
Awesome idea and bad ass realization @adrian! (pardon my French) I did not install yet but will do soon and check it out. As @szabesz said collaboration is the baddest part. I can expect a load of wise stuff to learn from those actions contributed by PW gurus. It just might happen that there will be a lot of actions - maybe put them in a folder? And one question about the backup. It seems it is custom and not integrated with db backup module. Is there a reason for that?2 points
-
Just to add to your testing, I can confirm that I have been using this awesome module with 3.x for probably 6 months now without any problems!2 points
-
Announcing that I've tested and can confirm that ImageMarker is compatible with ProcessWire 2.8.x and ProcessWire 3.x2 points
-
Just announcing that I've tested and can confirm that Matrix is compatible with ProcessWire 2.8.x and ProcessWire 3.x2 points
-
Nice! Just an idea: could the actions accept url params? Eg. prefill the template selector with "basic-page" using this url: /admin/setup/admin-actions/options?action=TemplateFieldsBatcher&templates=basic-page This would enable linking the action from other places of the admin (eg. add right-click menu option on pagelist, etc). Plus another idea: actions could be put into a subdir, if users start to contribute actions their number will increase. Btw I see you haven't overcomplicated the UI of the roles2 points
-
This is very cool. Both the module and the bundled actions will be super useful. Thanks!2 points
-
This functionality is now available via the "Delete Unused Fields" action in my new Admin Actions module:2 points
-
Thanks. I get it! The way @ottogal wrote, it didn't work. However, with your idea of array and a search on forum, I mix it with the Ryan's answer. So the final version is : foreach ($categ_team as $categ) { $content .= "<h2><a href='{$categ->url}'>{$categ->title}</a></h2>"; $cat_members = $pages->find("template=member, featured=0, categ_team=$categ, sort=-date_begin"); $years_start = []; foreach ($cat_members as $cm){ $years_start[$cm->date_begin] = $cm; } foreach ($years_start as $y){ $content .= "<h3>{$y->date_begin}</h3>"; //or apply some formatting to the $y value $members = $cat_members->find("date_begin=$y->date_begin"); foreach($members as $m) { $content .= "<h4><a href='{$m->url}'>{$m->title}</a></h4>"; } } } Thanks!2 points
-
As an aside, I wish we had more devs here in South Africa. There's only two of us, I think: Larry Botha + team (an agency called Fixate) and myself. Our government sites could totally do with a ProcessWire upgrade.2 points
-
ImportPagesPrestashop You can download it here: ImportPagesPrestashop With this module you can import your categories, products, features and images of the products to your new Processwire website! What does it? Once you've installed this module, a new tab will be under the Setup named Import Products from Prestashop. When you click on it, you can make connection with your Prestashop DB. After making the connection you can import first the categories, followed by products and the features and the images will be inserted in the fields of the product that is linked to these features and images. You can choose whether you import your categories et cetera in as much languages as possible or only in your default language. You can also choose to import the EAN-number and/or the products and the Reference code of the products. Requirements Only tested it so far on Processwire 3.x. Installation Download the zip file, upload it to your Processwire site and install it. Languages If you want this module to run as smooth as possible, name your languages like in the screenshot below. If you want to execute this module in dutch, download the .zip file, go to your languages tab in processwire, go to your dutch language and upload that .zip file to your site translation files. Credits to djuhari NL-Translations.zip1 point
-
UIkit provides a flex, form and button component. And if you are using Sass or Less, you can install UIkit for example with Bower and import only the partials you need. Here is what the import would look like in Sass: @import "../../bower_components/uikit/scss/uikit-mixins.scss"; @import "../../bower_components/uikit/scss/uikit-variables.scss"; @import "../../bower_components/uikit/scss/core/flex.scss"; @import "../../bower_components/uikit/scss/core/form.scss"; @import "../../bower_components/uikit/scss/core/button.scss"; That way you still would have a lightweight framework. Regards, Andreas1 point
-
Thanks, I am actually in need of that feature in a current project. So hurry ... jk edit: As far as I know the page field stores multiple values just as comma separated ids1 point
-
@kongondo, at the end of the select chain one might want to select multiple things, like on regular page selects. For example a list of employees: Company > Location > Department > Jane Doe, John Doe and Max Mustermann1 point
-
1 point
-
@FrancisChung good question. Any business logic should be separated from the view layer. A template is a view, code there should not be complex. Loops, perhaps some string concatenations, value calls, nothing more. You want a template designer not to fiddle with your code and perhaps even break something. Even if you are the template designer. For complex logic use Modules, Template Data Providers or something like the Controller/View separation used in Template Engine Factory I understand that this is perhaps not the ProcessWire way, right out of the box, or at least not something that is advocated too much, but I think it's because ProcessWire does not dictate how you use it. MVC ... or just VC in this case is just one way to do it. For simple sites perhaps overkill but if your code grows more complex, the VC concept makes the project more sustainable and it's a well established concept.1 point
-
Dynamic Selects version 004 (released (30/11/2016)) Glad to announce that the latest release of Dynamic Selects is now available for Download/Purchase. Changelog Dynamic Selects is now fully compatible with ProcessWire 2.8.x and ProcessWire 3.x.1 point
-
Every site I build has an own module, where I put all my hooks and additional logic. Also I use an autoloader there to load all the custom classes. They reside in a psr-0 structure within the modules directory. Anyway, I would not recommend using class calls within your templates, rather encapsulate all logic/data needed by the templates in module properties/methods. Perhaps the TemplateDataProviders module might interest you.1 point
-
Looks like your field is returning an array of author options, so try: <?php echo $page->author->first()->fullname ?> You can also use: last(), or eq(n) The other approach is to foreach through each author: foreach($page->author as $author) { echo '<p>'.$author->firstname.'</p>; }1 point
-
Ok, the optional author links are now available. These are the current options: protected $authorLinks = array( 'pwforum' => '985-adrian', 'pwdirectory' => 'adrian-jones', 'github' => 'adrianbj', );1 point
-
I'm doing a modded implementation on a new project using PW 3.0.41 right now. Works like a charm.1 point
-
Let's inform them Jokes aside, the db backup module is supported by Ryan, so it should be safe to rely on it. Sensible use cases would dictate to try things out in a development environment not on a live site, so I would not worry too much about this.1 point
-
Anything for the community here! Well spotted. You know it definitely works then1 point
-
All UK users should start using a VPN now ... and configure / test it so that it's not leaking their IP. Not all VPN providers are the same. I recommend AirVPN which I've used for several years now.1 point
-
Thanks for the detailed answer @BitPoet ! I'm going to get my hands dirty right away and see how things go. The journey begins1 point
-
@netcarver and others, just wanted to let you know that the functionality of this module is now available as an action in my new Admin Actions module:1 point
-
Hello member, I just install processwire and hopefully I can learn more from this forum.1 point
-
It’s ironic that they release this tool on the day the Snooper's Charter law became official in the UK. The new surveillance law (Investigatory Powers Act) requires web and phone companies to store everyone’s web browsing histories for 12 months and give 48 official groups full access to the data - one of these groups is the GCHQ. These groups will also gain new powers to officially hack into computers and phones to collect communications data in bulk. http://www.wired.co.uk/article/ip-bill-law-details-passed1 point
-
Made by Government Communications Headquarters in the UK.1 point
-
That's mostly because it's not a simple problem to solve at all. Merging of changes happening in two independent systems cannot work simply by clicking a button. There are various ways to make it work, which all come with their own kind of backdraws. With each project having different goals/needs it's a matter if choosing the one giving you the least pains, while helping you enough to make it worth. Also I'm not sure if I missed some beta statement in my modules topic, but it's really stable. Any upcoming changes should only affect the accompanied cli tool. Also I've it in production usage for over a year now with no issues in the latest months.1 point
-
1 point
-
BTW: Shouldn't that be $pages->find( So that naming is rather misleading. A proposal (written just here, not tested): foreach ($categ_team as $categ) { $content .= "<h2><a href='{$categ->url}'>{$categ->title}</a></h2>"; $cat_members = $page->find("template=member, featured=0, categ_team=$categ"); $years_start = array[]; foreach ($cat_members as $cm){ $years_start[] = $cm->date_begin; }; $years_start = $years_start->unique(); foreach ($years_start as $y){ $content .= "<h3>{$y}</h3>"; //or apply some formatting to the $y value $members = $cat_members->find("date_begin={$y->date_begin}"); foreach($members as $m) { $content .= "<h4><a href='{$m->url}'>{$m->title}</a></h4>"; } } } Edit: Small correction.1 point
-
@thlinna I do not know if it will be of any help, but I myself do not migrate any db at all. Instead I build my workflow around this: http://tltech.com/info/mysql-via-ssh/ I put together a bash script to completely automate the process, and normally I can clone the live db to my local machine in seconds (small databases...). This way I always have to work on the live site to make all the necessary changes, afterwards I have to clone the db, but it is an easy to follow workflow and dead simple It might be too simple for teams, but a solo developer cannot go wrong with it, at least I'm quite happy with it, I got used to working this way. Sure, I have never had to work with really big databases, but these days even transferring dozens of megabytes does not take long.1 point
-
1 point
-
Hi gunter and welcome to PW. I am not sure why you are losing fields - perhaps you can elaborate, but regarding template name changes - if you go the advanced tab of the template settings you can rename the template. You can also choose to use an alternate template filename if that is at helpful in your scenario. Hope that helps.1 point
-
There's more than one way to achieve this and you can find more comprehensive examples around the forum, but this is roughly the concept I've been using (simplified a lot for this example.) Let's say that you put this in your home template (/site/templates/home.php): <?php // this is your template file, or a controller if you will: $view = new TemplateFile(); $view->some_param = "PW"; $view->filename = $config->paths->templates."views/{$page->template}.php"; echo $view->render(); Then you add a view file corresponding to filename you've defined at controller (in this case /site/templates/views/home.php): <?php // this is your view file: echo "<h1>I'm view for {$page->template} and title is {$page->title}!<h1>"; echo "<h3>{$this->some_param} rocks!</h3>"; echo $page->body; This should be a working example, though not very useful yet. You could expand it by having your view files (or templates themselves) include other files ("partials" or just "include files" depending on terminology, for a global header and footer etc.) or have multiple view files for each template.. and so on. Of course you could also achieve similar results with includes instead of TemplateFile object, though I personally like how this method separates controller from view layer. As always, with ProcessWire imagination is your only limit1 point
-
For the other part of it, in preventing the duplicates. As mentioned before, the pages you retrieve are already going to be unique. But like you said, you may have duplicate field values even among unique pages. Lets say that you wanted to guarantee the uniqueness of a 'title' field, for example: $uniqueResults = array(); foreach($results as $resultPage) { $uniqueResults[$resultPage->title] = $resultPage; } Following that, there will be no pages with duplicate titles in your $uniqueResults array. You can take the same approach with any other field(s). Though make sure your field resolves to a string before using it as a key in your $uniqueResults array.1 point