Leaderboard
Popular Content
Showing content with the highest reputation on 07/01/2014 in all areas
-
There's a new version available. Now supporting file versioning to handle the caching issues of CloudFront. There's an option on the module configuration that will automatically rename the uploaded files by inserting a timestamp in the file name. This way all the files have unique names and that will make it easier to replace old files already cached by CloudFront (something that can be a huge PITA as many CloudFront, or other CDN systems know well).5 points
-
If you want to 404 that situation, add this to your .htaccess file, somewhere after "RewriteEngine On": # ----------------------------------------------------------------------------------------------- # Send URLs with non name-format characters to 404 page # ----------------------------------------------------------------------------------------------- RewriteCond %{REQUEST_URI} "[^-_.a-zA-Z0-9/~]" RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?it=/http404/ [L,QSA]3 points
-
Specify the field you want to filter from the page as subfiled, e.g. hue.title~=$q3 points
-
Reed makes an interesting point about social networking - I don't care what anyone says, but Social Networks can be a really bad way of keeping people informed and companies are falling for this left, right and centre: It can seem flippant and cursory It can lack detail It often relies on the client having to do the running to find information You don't know whether you are dealing with someone serious or just a back-office PR lacky Your important communique is surrounded by non-relevant information, advertising, animations and an inappropriate environment They are incredibly impersonal, ironically It strikes me that a good communication system should be exclusive to a company, and in the case of something like Servint, should be completely external to the system it is talking about (so it does not go down with the rest of the system). The blog post that Reed has written should have been available during the incident and should have been emailed out to every contact email address they have. Clients should be encouraged to make sure that they have registered an emergency email address (or several) where notifications are sent. Emails should NEVER say "Keep up to date by following us on twitter," or "check our blog often," or anything else that means the client has to do the work - updates should be regular and emailed so the client has to do nothing. Servint have a really good reputation, from what I see, for being very technically able. But any reputation is made up only partly by a company's history for being good - the rest (possibly the bigger part) is based on how they communicate with their customers; how much detail they give, how often they supply information and how direct and personal are those communications. With the advent of social networking, companies (most companies, probably), have abandoned good personal relations in favour of bulk, cheap, impersonal relations via facebook and twitter. Companies should use these systems, they are fun and chatty - but they are not personal. When the muck hits the fan, they need to deal directly with the customer, not via a third party.3 points
-
@Joss: it's also a matter of knowing your customers. Being in the same channels and not forcing them to use the channels you've chosen. In this regard I appreciate what ServInt were trying to do, i.e. using Twitter and Facebook to communicate to clients already in those medias. What they failed at was that they sent out one quick message, neglected keeping people up to date as things evolved and didn't even reply to messages of frustrated clients as those kept piling up. Twitter is very fast-paced media; if you stay silent for five minutes, people decide that you're gone (or just don't care) and start asking for status updates. Unless you answer them, they're going to be pissed My opinion is, of course, hugely affected by the fact that 100% of time I'm in some way connected to social media, so if a service provider wants to reach me, that's their best bet (and the number one media I'd check if something was acting up would be Twitter, which is perfect for quick status updates). Not saying that using Twitter would eliminate the need to send important updates as emails, but it can provide very real extra value to a lot of customers. (Also: if my service provider sent me an email each time there's been some little slowdown or a minute of downtime, I'd be equally pissed at them. Each media has it's own merits and email isn't that great for fast-paced messaging. When you're having this scale of an issue it should've been used, though.) On slightly related note, I found that blog post somewhat lacking. Sure, they're saying that things went wrong (+1 for explaining what the issue was), but the rest was mostly just saying that "shit happens" and "we'll try to be better". I'd have expected them to name at least one concrete step they're taking to make sure that this doesn't happen again -- "we're going to learn from this" is abstract and in itself doesn't promise any improvement at all. Communication is a difficult beast to pin down perfectly2 points
-
Page lister uses has_parent!=2. There could also be pages under admin without admin template.2 points
-
sort() accepts a selector https://processwire.com/api/selectors/ and that is not one. Try $dmcs->sort("parent.title"), although i'm not sure it will work.2 points
-
ProcessWire has no theming system like Drumlapress - basically because it does not need one. Anything you can do with html/css/js can be used with ProcessWire. Dead Simple Example: Create a file in /site/templates/ called mytemplate.php Go to the admin, go to setup -> templates and add new. You will see mytemplate.php listed. Select it and create the template. It will automatically have the title field added. Now, go to the front end of the admin, to the pages list, click on Home and then click on New. This will create a new page under home. Select your new template from the drop down, fill in the title field (for example, "testpage") and save. Publish it. Go to the front end and go to yoursite.com/mypage/ It will be blank. Open your mytemplate.php and add this to the top: <?php echo $page->title; ?> Save and refresh the page - you will now see the page title, but with no formatting at all. However, you can now see that you can add any html formatting to mytemplate.php you like - use a framework like Bootstrap or work it out in dreamweaver, anything. All you have to do is to add the API like the example above to display content for that page. ProcessWire puts no limits on how you build your site and neither do you have to convert anything to work with it - you can create ANY design you like and not be tied up by someone elses design. What is more, you can do this by learning only the smallest amount of PHP (like, what you can learn in a morning) and by learning to use the very logical API. For a more detailed tutorial, go to http://wiki.processwire.com/index.php/Basic_Website_Tutorial2 points
-
ProcessWire Email Obfuscation (EMO) Download | GitHub Email Obfuscation module for email addresses with 64 base crypting. This module finds all plaintext emails and email links from the document and replaces them with span elements including configurable replace text. All the addresses are encoded to 64 base strings and stored in spans data attributes. Then on client side we decode these strings back to their original state. Install Create new 'EmailObfuscation' folder into /site/modules/ and place the content of this repository into the directory. Login to processwire and go to Modules page and click 'Check for new modules'. Find 'EmailObfuscation' and click install. You can make optional configuration changes in the module admin page. Thanks This is a ProcessWire module fork from MODX Evolution plugin emo E-Mail Obfuscation. http://modx.com/extras/package/emoemailobfuscation EDITED ON: 2013-03-03 - Added description. 2020-04-16 - Fixed GitHub links and updated description. Hello all. Just found PW few days ago and it's already looking awesome! Here comes first contribute and some questions for developing it further. There was one existing email obfuscator on reposity that didn't use any crypting for addresses so I decided to do a little test run and port the one that we currenly use with MODX Evo to ProcessWire module. I'd like to make PageAutocomplete like gonfigure option to admin so that one could select and set templates to exclude module action. It looks like autocomplete is tied to pages and since templates are not set to system as pages this is option is no go, am I right?1 point
-
By default, the "Forgot Password" module is not turned on in v2.1. My thought was that lack of such a function is technically more secure (on any site or CMS). Why? Because having such a function active means your password is only as secure as your email (*though see note at end of this message). So I thought we'd start things out as secure as possible and let people adjust it according to their own need. But I'm rethinking that decision, and may change it to be 'on' by default. If you don't already have that "Forgot Password" module installed, it is relatively easy to reset your password with the API. Lets say that you lost the password for your account named 'admin' and you wanted to reset it. Paste this code into any one of your templates (like /site/templates/home.php in the default profile, for example): <?php $admin = $users->get('admin'); $admin->setOutputFormatting(false); $admin->pass = 'yo12345'; // put in your new password $admin->save(); …or if it's easier for you to copy/paste everything on one line, here's the same thing as above on one line: <?php $users->get("admin")->setOutputFormatting(false)->set('pass', 'yo12345')->save(); Replace "yo12345" with the new password you want and save the template. Then view a page using that template (like the homepage, in our example). The password for that account has now been reset, and now you are ready to login. Don't forgot to now remove that snippet of code from the template! Otherwise your password will get reset every time the page is viewed. Once logged in, here's how to install the Forgot Password capability: 1. Click to the "Modules" tab. 2. Scroll down to the "Process" modules. 3. Click "Install" for the "Forgot Password" module. That's all there is to it. You will now see a "Forgot Password" link on your login page. *ProcessWire's "Forgot Password" function is actually a little more secure than what you see in most other CMSs. Not only do you have to have the confidential link in the email, but the link expires in a matter of minutes, and PW will only accept password changes from the browser session that initiated the request. So an attacker would have to initiate the password change request and have access to your email at the same time, making it a lot harder for a man-in-the-middle snooping on your email.1 point
-
Here are some API additions to the dev branch, primarily for WireArray/PageArray/etc. I've found these very handy lately, and would have on almost any project I worked on, so decided they'd add value to the core. I'll add these to the cheatsheet once 2.4 replaces 2.3, but for now, here they are. The examples here use PageArray, but note that these API additions apply to any WireArray derived type, not just PageArray. WireArray::implode() Implode all elements to a delimiter-separated string containing the given property from each item. Similar to PHP's implode() function. Usage: $string = $items->implode([$delimiter], $property, [$options]); Arguments: $delimiter - The delimiter to separate each item by (or the glue to tie them together). May be omitted if not needed $property - The property to retrieve from each item (i.e. "title"), or a function that returns the value to store. If a function/closure is provided it is given the $item (argument 1) and the $key (argument 2), and it should return the value (string) to use. [$options] - This argument is optional. When used, it's an array with modifiers to the behavior: skipEmpty: Whether empty items should be skipped (default=true) prepend: String to prepend to result. Ignored if result is blank. append: String to prepend to result. Ignored if result is blank. Examples: $items = $pages->find("template=basic-page"); // render all the titles, each separated by a <br>, for each page in $items echo $items->implode('<br>', 'title'); // render an unordered list of each item's title echo "<ul><li>"; echo $items->implode('</li><li>', 'title'); echo "</li></ul>"; // same as above, but using prepend/append options, // this ensures no list generated when $items is empty echo $items->implode('</li><li>', 'title', array( 'prepend' => '<ul><li>', 'append' => '</li></ul>' )); // same as above, but with all items now presented as links // this demonstrates use of $property as a function. note that // we are also omitting the delimiter here as well, since we don't need it echo $items->implode(function($item) { return "<li><a href='$item->url'>$item->title</a></li>"; }, array('prepend' => '<ul>', 'append' => '</ul>')); WireArray::explode() Return a plain array of the requested property from each item. Similar to PHP's explode() function. The returned PHP array uses the same keys as the original WireArray (if that matters). Usage: $array = $items->explode($property); Arguments: $property - The name of the property (string) to have in each array element (i.e. "title"). You may also provide a function/closure here that should return the value to store. When a function/closure is used it receives the $item as the first argument and the $key (if needed) as the second. Examples: // get an array containing the 'title' of each page $array = $items->explode('title'); // get an array containing the id, url and title of each page $array = $items->explode(function($item) { return array( 'id' => $item->id, 'url' => $item->url, 'title' => $item->title ); }); WireArray::data() Store or retrieve an arbitrary/extra data value in this WireArray. This is exactly the same thing that it is jQuery. I've personally found this useful when building search engines: the search engine can store extra meta data of what was searched for as a data() property. Then any other functions receiving the WireArray/PageArray have access to this additional info. For example, the search engine portion of your site could populate an array of summary data about what was searched for, and the render/output code could render it to the user. Usage: // Setting data $items->data('key', 'value'); // Getting data $value = $items->data('key'); // Get array (indexed by key) of all data $values = $items->data(); Arguments: The above usage section explains all that's needed to know about the arguments. The only additional comments I'd make are that 'key' should always be a string, and 'value' can be anything you want it to be. Example: function findSkyscrapers() { $floors = (int) wire('input')->get->floors; $year = (int) wire('input')->get->year; $items = wire('pages')->find("template=skyscraper, floors=$floors, year=$year"); $items->data('summary', array( 'Number of floors' => $floors, 'Year constructed' => $year )); return $items; } // the render function can focus purely on output function renderSkyscrapers($items) { echo "<h2>You searched for:</h2>"; // render the summary of what was searched for foreach($items->data('summary') as $label => $value) { echo "<p>$label: $value</p>"; } echo "<h3>Skyscrapers found:</h3>"; // note use of new implode() function, though a foreach() would be just as well here echo $items->implode(function($item) { return "<p><a href='$item->url'>$item->title</a></p>"; }); } WireArray::and() WireData::and() Return a new copy of the WireArray with the given item(s) appended. Primarily as a syntax convenience for various situations. This is similar to jQuery's add() and andSelf() functions, but I've always felt "add" implied adding something to the original rather than creating a new combination, so went with "and" in this case. The term "and" is actually a reserved word in PHP, so you can't usually have a function named "and()", but through the magic of hooks, ProcessWire can. This function should reduce the instances in which you'd need to do "$a = new PageArray();" for example. Usage: // create a new WireArray with $items and $item (appended) $myItems = $items->and($item); // create a new WireArray with $items and $moreItems (appended) $myItems = $items->and($moreItems); // create a new WireArray with $items and $item (prepended) $myItems = $item->and($items); // create a new WireArray with $item and $anotherItem (appended) $myItems = $item->and($anotherItem); // create a new WireArray 4 items $family = $pappa->and($mamma)->and($brother)->and($sister); Examples: // generate breadcrumb trail that includes current page foreach($page->parents->and($page) as $item) { echo "<a href='$item->url'>$item->title</a> / "; } // check if page or its children has a featured checkbox if($page->and($page->children)->has("featured=1")) { echo "<p>Featured!</p>"; }1 point
-
Hi, just wanted to say hello to PW. Some former WebsiteBaker users made me aware of PW, so I decided to give it a trial this weekend. From my past CMS experience, I decided to convert an existing SilverStripe template into PW from scratch. This way you will quickly get a feeling about the system itself, the backend, template system and available documentation. After watching two videos and reviewing the API documentation, I started over and had a clone of my SilverStripe site running in less than two hours. I started with WebsiteBaker back in 2006, did some sites with ModX and Contao (formerly known as TypoLight) and was even forced to deal with WordPress by one client, before I finally switched to SilverStripe around 2009. My first impression of PW was: cool little CMS with easy backend, awesome API. Somehow feels a bit like a mixture of WebsiteBaker, Contao and SilverStripe to me, taking the best from all of them while skipping the bad parts. Respect. Looking forward learning more about PW. Cheers cwsoft1 point
-
Diogo, you're a star. It worked. The result: http://dmc.dudmc.com/about-du-and-dmcs/what-is-a-dmc-destination-management-company/1 point
-
I totally agree. It's not even my own wish, but I hear it more often in the past year since more and more people are considering PW as an alternative. I think such a feature would be a good reason for CMS switchers and/or a good marketing thing. You know, like "look how flexible it is, you can build your page even in the backend very individual with drag&drop and eye candy and such stuff... blah blah" ;-) PageTable is great, repeaters are great, all the new pro fields and of course all your modules are great. The flexibility is endless. You know that, I know that, every experienced PW user knows that. But - as I said - for marketing reasons such at a first glance flexible features or on the other hand the learned and for several years used solutions like a central media manager would be nice. They could be built on top of the PW core without losing the PW paradigms. People are not interested in how something works as long as it works for them1 point
-
Page tables field supports multiple templates unlike repeaters. So it's possible now with dev.1 point
-
I think the main "click" you need in your head is understanding the concept. Everything is a page with fields. See it as data container. You need to reuse pages or their fields? Put them somewhere hidden and reference them where needed. You need some kind of repetition of content? Use repeaters or sub pages. Or take a look at this differentiation from our master: Comparison of Repeaters, PageTables etc. The only thing ProcessWire cannot do (yet): A kind of repeater where you can define the kind of content block you insert (like TYPO3 or Contao does). But also this can be done with a clever combination of repeaters and PageTables and... whatever. There always is one or more ways1 point
-
This is not a problem. Forget the idea of categories as a separate thing for the moment - they are just pages. So, for instance, you can have this structure: Home -- News ---- Politics ---- Religion ---- Coffee And then under each of those you would have the actual posts. The template for the posts would include a page field. That page field would be set for a single selection and then the parent set as the News page. On the input settings for the page field you would pick the input field type of your choice and then also enable being able to create a new page directly from the field. When someone creates a post, they would be able to select a category or create a new one. The drawback for this is that you could end up with thousands of categories if people go silly! Also, if you want the category pages to have additional details about the category (and intro paragraph, icon, whatever) then you will have to go back and edit those pages. But essentially, what you want to do is very easy indeed.1 point
-
It really depends on the site concept. Using pages for these subsections might offer more flexibility, repeaters might be simpler for editors. (I'm not opposed to using repeaters that way, I just haven't used them that way myself – yet.) I know the whole “there's more than one way to do what you want to do” approach in PW can be confusing when you first get started. Then again, it does offer a great flexibility to react to individual site concepts and user needs. There almost always is more than one way, just pick the one that you feel works best in any given scenario.1 point
-
Thanks for the fast replies (this community rocks) "my" image field allows for multiple images. It is possible to (re)upload the "c" image in "b", appending it to b's images. I understand that repeaters internally are nothing but pages, so if PW ties images to pages, they are tied to the repeater context, ok. I'm wondering,though; the image option in the wysywig is able to browse through images already uploaded, even on other pages, so there seems to be a way to get to the already uploaded images. The concept of a central image repo and page selector sound interesting, I'll look into that. For the current smallish site, I'll stick with re-uploading the image. Out of curiosity, how would you handle text/image content on a page if there can/may be one or more of these sections? Hidden subpages, collected on the parent page? I'm still in the baby steps mode, so any nudge in a more proven direction is welcome Thanks again for the support.1 point
-
Greetings, I'm glad Reed posted that. For me, I got some sleep and am better able to just chalk it up to ridiculously bad luck for all involved -- clients and ServInt. Propagating information like this also helps those of us who need some support when clients want to know what happened. Like all adversity in life, I'm hoping that, through this, we all learned something and will be wiser and stronger. Thanks, Matthew1 point
-
I have just finalized support for all Profields field types: Table, PageTable, Multiplier, and Texareas Please check out the latest version and test away. I think this completes enough functionality now that I am ready to release this to the modules directory once I get some feedback to verify that multi-language functionality and the Profields additions are working well. The official release will probably still be "alpha" for a little while, but hopefully getting it in the modules directory will get some more people testing!1 point
-
Hello, thanks for the replies so far. @renobird: will try the upcoming PW 2.5 from the DEV branch today. @Mike Anthony: forgot Drupal 6+7 on my CMS list Cheers1 point
-
Processwire does not have front-end themes, because for every website the front-end is custom made. https://processwire.com/talk/topic/6653-how-can-i-apply-a-new-theme-to-processwire/ The install.sql contains the default (admin) pages which are needed for the back-end, and some default pages for the front-end (Home, Basic Page, Search, 404) There is a module to export an entire site profile, this will create an sql export that together with the other file from the site folder can be used when installing new sites with that specific site profile. Site Profile Exporter http://modules.processwire.com/modules/process-export-profile/ A good read to get you started https://processwire.com/talk/topic/4173-grouped-forum-posts-links-articles-tutorials-code-snippets/1 point
-
You're mixing up things. This should be more like include("/home/xyz/public_html/pw/index.php"); wire("user")->language = wire("languages")->get("en"); $referenzen = wire("pages")->get("/referenzen/"); $references = $referenzen->children; foreach($references as $reference) { echo "<li class='references-item'>"; echo "<p>{$reference->title}</p>"; echo "</li>"; }1 point
-
Hi, and welcome cwsoft I'm also pretty new around here, having fully switched to ProcessWire a little over a month ago. I, too, came from various different systems (PyroCMS, SilverStripe, WordPress [yes, also forced ], Typo3, and Drupal). PW has really done a good job at melding everything together in such an elegant, and simple, fashion. So yeah, welcome to the club @renobird: I can't wait for 2.5 - going to give the dev branch a try today.1 point
-
Welcome cwsoft. If you haven't had a chance yet, definitely try out the dev branch. There are some fantastic new things already committed. ProcessWire 2.5 is going to be a giant leap.1 point
-
There also the Email Obfuscator module which needs JS to decode the obfuscated addresses (might or might not be con for you).1 point
-
Here's a module by Roope: Email Obfuscation module for plaintext emails and email links with 64 base crypting. Here's an interesting method that would be cool to see as a module: http://johnhaller.com/useful-stuff/obfuscate-mailto http://johnhaller.com/useful-stuff/obfuscate-mailto/code-php1 point
-
Hi Adrian, I managed to get this to work by comment out the following on line 2106: $valid_files = array(); if(is_array($files)) { foreach($files as $file) { //if(file_exists($file['currentpath']) || file_exists($file[0])) /* <-- This line */ $valid_files[] = $file; } } I've tried an import into another site and it works There may be implications I'm not aware of by doing this? Edit: Just tried with latest version 0.1.9 and that works too. Line 2106 in version 0.1.6 is now line 2144 in version 0.1.9 I did get this warning after the import to the new site both in versions 0.1.6 and 0.1.9: Warning: rmdir(C:/xampp/htdocs/mysite/site/assets/files/1022/migratorfiles): Directory not empty in C:\xampp\htdocs\mysite\site\modules\ProcessPageTreeMigrator\ProcessMigrator.module on line 21821 point
-
For your first scenario I can't quite see what the big benefit of session would be, though that depends on the structure of your page and the way you build this thing in the first place. Some possible solutions I'd consider: If the edit view opened in modal box is an external page (not part of this page or put together on the fly) then you'll have to somehow let it know what it is that you want to edit.. and in that case I'd rather provide it with page ID and field ID (or name) as GET params. If the edit view is generated and filled out on the fly (and submitted by AJAX, I'd assume) you can just grab the content from page using JS without the need to store anything in session variables. In your second scenario I'd also consider using GET params (specify comment ID to quote from) or storing either the comment ID or even the whole quoted text (unless you really need to support storing *a lot* of data) in JS cookie. This is an example of situation where you probably don't need to make sure that quoted text is somehow protected (in most cases user can edit it upon posting anyway), so storing that data in session provides very little extra value. -- Considering sessions vs. other methods of storing run-time data in general: Biggest reason I tend to avoid sessions is that as the amount of data stored in session grows in size, so do the memory requirements (and, in extreme cases, also the disk space requirements) of your site. At least some PHP versions load whole session data to memory when session is started, so you can imagine what having tens of kilobytes, hundreds of kilobytes or even megabytes of data (a worst case scenario, but still) does on a site with a lot of simultaneous users. With sessions you'll also want to make sure that you're cleaning stored session files properly (which, by the way, isn't always as trivial as it may sound) and preferably clearing stored values run-time too, especially if you're storing a lot of content. GET params, on the other hand, don't consume any extra memory.. and storing stuff in JS cookies only consumes client resources. As for why one would prefer to use sessions, biggest benefits are that a) session variables make it possible to "hide" the mechanism behind this all from the user and b) session data is much harder (practically impossible, unless you've made it possible yourself) to tamper with (it's easy to try out different values for GET params or alter data stored in JS cookies). Ease of use is a very real benefit too, of course. Storing data in session variables is often the least painful route. Tradeoffs, tradeoffs.. but then again, isn't that what web / software development is always about?1 point
-
@Ryan, I've been meaning to mention how awesome these additions are, I use implode() and data() a ton. data() has been particularly useful for passing stuff to markup files.1 point
-
@Jonathan: Hi, it's me again, - I have some more thoughts / suggestions If someone want to use your optimize module and simply the ImageSizer (or any replacement of it), it's just fine as is. But if someone want to use the PageimageManipulator and the Optimizer, the option to temporary suppress the Optimizer is needed: $image->pimLoad('prefix')->someManipulations()->pimSave()->width(300); // this works fine, no need to suppress the optimizer $image->width(300)->pimLoad('prefix')->someManipulations()->pimSave(); // this doesn't work, we need to suppress the optimizer in the width(300) call! // we only want to optimize the final variation and don't want optimize intermediate images Next points all regard to pageImageOptimize() / pageimage::optimize(): With the initially module, the pageimage::optimize() was made for original images only. To preserve the original source (for quality etc) you create a variation with a name like basename.jo.jpg. That's all perfect. There is only a little issue: with the .jo in the name of the variations they get not fetched by the pageimage variation collections. As a result, when deleting / removing original images, these variations would stay as orphaned files. So, I know there is currently no way provided by PW to solve that (But there is already a private discussion with Ryan on how to provide a good support for custom imagefilename suffixes) As a quick (but bit clumpsy) workaround, you can change the .jo by a .0x0 - This matches the current used regex of the variation collections and isn't a name that could already exist. Not only after the use/need for the temporary suppression of the optimizer, there are application cases where someone need / want to call pageimage->optimize() not only on original images. For example when working with the PageimageManipulator: $image->pimLoad('prefix')->someManipulations()->pimSave()->optimize(); // here simply the existing file should be optimized, no need for a new variation name or a new pageimage object I have updated the pageimage::optimize() to recognize original images vs variations and act upon that. If the basic usage supports individual options per image, the optimize hook needs too: $options = array('joQuality'=>80, 'joThreshold'=>30); $image->optimize($options); ----------------- Finally some thoughts about how the different Pageimage modules could work together - If you implement support for PNG too, a name change to something like PageimageOptimize (PageimageOptimizer) would be useful. - Could it be useful for the average user that you do a check against the ImageSizer quality (hook)-before resizing? And if there is no individual setting, temporary set it to 100%? This way an average user do not have to know all about how it works best. And all users can save some code writing, no need for: $options = array('quality'=>100); $image->width(300, $options); just type $image->width(300) and get the best possible result. - with the PageimageSizerImagick (formerly known as ImagickResizer), the user can choose what type of metadata he want to keep, EXIF, XMP, ICC-profile. XMP isn't supported by JpegOptim, but the others too. Would it be useful to support these with the Optimizer? I can imagine that both modules have their own global settings in their config screens, but both check for individual settings on a per image basis: $options = array('keepEXIF'=>false, 'keepICC'=>true); $image->width(1200, $options); $image->optimize($options); I think their will be some more Sizers in the future, PageimageSizerImageMagick, PageimageSizerNetpbm, PageimageSizerWhatever and all of them should support and use the same options where possible. This way a user can write code for image handling independent of the image rendering engine. What do you think about this? I know its much at once and I have a bit of a guilty conscience to push so much stuff here. But I think it is needed that the existing and future image modules work well together and just by installing / uninstalling them.1 point
-
Table Use this for tabular data, like rate tables or other things that you might typically represent in a spreadsheet. Use it for situations where you don't need the full-blown flexibility of repeaters, as it's technically more efficient with far less overhead than repeaters. Something like the Events Fieldtype could be very easily re-created via a Table field, but the potential uses are far broader. But for the most part, think tabular data when it comes to the Table field. Multipliers This is good for when you need a range of values (whether text, textarea, numbers, dates, etc.). If you are using repeaters with just one field in them, you might be a lot better off with a Multiplier. Like the Table field, Multipliers are very efficient and low overhead relative to something like Repeaters. Use Multipliers when you need to repeat a single input multiple times, optionally with a min and max number of inputs. Lets say you are building an employee directory, and each employee has between 1 and 3 email addresses. Rather than using 3 separate email fields, you would use 1 multiplier field and specify min=1 and max=3. Repeaters These are infinitely flexible in terms of what they represent, but each row of values is technically a page in the system. As a result, with the flexibility comes significant overhead. This is really only an issue when the quantity of repeater items gets high, or when you have lots (thousands) of pages using repeaters. I recommend repeaters for setting up things like homepage carousels. For example, if you go to the Villas of Distinction homepage, there are 3 separate repeaters in use on that page, each holding a photo, title, description, link. The client can have as many items in each of those sections as they want. Currently it looks like the first repeater as 6 items, the 2nd has 2, and the 3rd has 6. The possibilities of what can be represented with repeaters is endless, but look for potential alternatives when dealing with large quantities (whether large quantities of repeater items, or large quantities of pages using repeaters). PageTable This is one of the ProFields that is available for free (thanks to Avoine sponsorship) on the ProcessWire dev branch. Meaning, it'll be available for everyone to use as part of the core in ProcessWire 2.5. And you can use it now if you don't mind running the dev branch. PageTable has all the flexibility of repeaters, but with lower overhead from the admin/input perspective. Rather than trying to bundle all the inputs on one screen, PageTable shows you a table of items and you click on the item to edit it in a modal window. This enables it to be a lot more efficient from the admin UI perspective. It's also more flexible than repeaters are in terms of where you store your items. PageTable lets you choose where they should live, whether as children of the page being edited, or as children of some other parent page you designate. They might be a little more work to setup than repeaters, but I think that most situations where you need the flexibility of repeaters may be better served by PageTable. PageTable still can't compete with the speed and efficiency of Table or Multiplier, but consider using PageTable anywhere that you might have used Repeaters before. Repeaters and PageTable are fundamentally different from the admin UI/input perspective, so you'd want to compare them yourself to see what suits your individual input needs better. PageTable involves more clicking to create and edit items, making Repeaters potentially faster for entering data rapidly. But PageTable will scale much further in the admin UI than Repeaters will, so I would personally favor PageTable in more situations than Repeaters.1 point
-
There so many ways and use cases. I think with creating your own ProcessPageAdd module like Ryan mentioned would be a way to go, though depends on the case and you might need to maintain it in case the core one has changes that need to be implemented in your copy too. To use existing ProcessPageAdd you can hook into execute or buildForm. The latter being better as it returns the form not rendered so you can manipulate it. The ProcessPageAdd module also stores the template ($this->template) in case the Template family settings is set to only one specific, but this property is protected so you can't read it from outside the module. But you can add your own checks to get the parent and check for the family settings of its template. $template->childTemplates. Then use this info to check if it's your template you want to make changes. If you get this far you can also add fields to the form you wish to. These may even existing fields you are using on your page you create, and they will get saved along with the page add form. Just as an example to do what I said above: $this->addHookAfter('ProcessPageAdd::buildForm', $this, 'hookProcessPageAdd'); public function hookProcessPageAdd(HookEvent $event){ $process = $event->object; $form = $event->return; // get the parent page if(isset($_POST['parent_id'])) { $this->parent_id = (int) $_POST['parent_id']; } else { $this->parent_id = isset($_GET['parent_id']) ? (int) $_GET['parent_id'] : 1; } $this->parent = $this->pages->get($this->parent_id); // get the template via the child templates // if only 1 defined if(count($this->parent->template->childTemplates) == 1) { $childTemplates = $this->parent->template->childTemplates; $this->template = $this->templates->get(reset($childTemplates)); } if($this->template == "post"){ // load an existing field and get its inputfield to add to the form // this will be save to the page if the created page has the field $f = $this->fields->get("date_published"); $inputfield = $f->getInputfield(new Page(),null); // add the field after the page name field $form->insertAfter($inputfield, $form->get("_pw_page_name")); // populate page name field with a timestamp $form->get("_pw_page_name")->attr("value", time()); } } So far so good. The page title field is global and is also used on the page add process, it's also required, so you can't ignore it. It would be possible to remove the title field from your template. To do this you have to make the "title" field not global (field advanced settings). Once removed it will not get added to newly created template, and also you can remove it from any template. BUT there's some drawback, since the title is not global anymore, it will never be shown anymore in the page add process also for other normal pages! This gets kinda tricky. You could remove the title field and after that make it global again, but then it will get again shown at the page add process even if the template has no title field anymore. ProcessWire doesn't know. Also when opening the template you removed the title field previously, it is added again to the fieldgroup, and you can't remove it. See? So maybe best bet would be to leave it alone and just remove it from the add page form in the hook, or just populate it with some value, and later use hooks to concat values on page save to set the title dynamic. $form->remove($form->get("title")); So with all this in mind you could add "firstname", "lastname" fields to the add form with ease. Then use a Pages::added and/or Pages::saveReady to populate the title after adding the page. Or you could also "hide" the title field on the template. When editing the template, click on the title field to open context editor, select for visibility "Hidden, not shown in the editor". This will "remove" the title field on the edit screen. But you can still populate it via API if needed.1 point