Leaderboard
Popular Content
Showing content with the highest reputation on 10/06/2016 in all areas
-
An amazingly comprehensive survey on what's cool and what's not. http://stateofjs.com/ Here is the Table of Contents for the Results http://stateofjs.com/2016/introduction/ Take a look through all the sections in the above, but if you are in a rush, most PW folks would probably be most interested in the frontend frameworks section: http://stateofjs.com/2016/frontend/11 points
-
https://hackernoon.com/how-it-feels-to-learn-javascript-in-2016-d3a717dd577f Just saying.9 points
-
Status update: JsonNativeField version 0.0.4 now has configuration options for all field types in the field's input settings. Coming up next is some more data validation (i.e. "don't shoot your foot" checking) both in the UI when switching input type and in the module code when saving to and loading from the db. This will be the major step towards moving the module from alpha to beta stage.4 points
-
Wow the Skyscrapper's demo takes a hard hit in that thread! Maybe updating the site is not as important as updating the demo? Just came to my mind, do we have a "What we don't like about PW" thread? *dodges tomato*4 points
-
Looking to hook up with a PW expert mentor on an ad hoc basis. Immediate requirement is to help refine my coding for a small but complex site. Site integrates with: - Stripe (created a module to work with the Stripe API for subscriptions). Unfortunately in this case, Padloper only works with once-off product sales. - BigCommerce shop (created a module to work with the BigCommerce API to assign subscribed PW members to a BC customer group & when a logged-in user clicks a on front-end link in PW, redirect & auto-login the user to the BC shop) - Campaign Monitor (created a module to work with the Campaign Monitore API to assign subscribed PW members to a CM List) - CMS Made Simple - Main site built in CMS Made Simple (header & footer pulled from CMSMS to display on the PW site on the same domain + some content). Ideally long term, main site will be converted 100% to PW. - Viddler (no module, simply an included PHP file to access the Viddler API to pull site-restricted videos) Site is built on ProcessWire 3.0.24 devns © 2016 using PHP v5.4.35 Immediate requirements: 1. Get site-initiated emails to send correctly using ProcessWireSmtp. Connection is OK and some emails go through but not all??? 2. Stripe web hooks not working on live site but did on development site User custom field not updated on receipt of Stripe hook event OR event not received at all 3. LazyCron does not seem to be working. Cache is recording times, etc but no notification emails being sent. Maybe related to point 1 or I have stuff in the wrong place. 4. Need front end 'Forgot Password' to work. Tried module FrontendUser but it wasn't satisfactory and have reverted to FormBuilder with custom layout, PW 3.0+ option D, for login (in dev not yet on live login page). Ideally ForgotPassword would work for either user entered username or useremail. Done thanks to Am sure I could post my issues in the forum but would rather solve these problems first then help others with "how to" forum posts. Be my ProcessWire guru & PM me with your experience, hourly rate etc. Cheers psy3 points
-
Ah sorry - have a good read through this: https://processwire.com/api/fieldtypes/images/ But in essence, if it's not set to 1 then it returns an array of images, so you can either set to 1, or use this to get the first image. You can also use last() or eq(n) to specify a specific image. $panel->image_single->first()->size(400,200)->url3 points
-
May I ask, where you got this code? $event->zeit is neither a function, nor a object you could call methods on. It's either a timestamp (integer) or a formatted string. I'm using this hook in my ready.php to have something a bit like you wanted to use: $wire->addHook("Page::getDate", function(HookEvent $event){ $page = $event->object; $fieldName = $event->arguments(0); $dateFormat = $event->arguments(1); $empty = $event->arguments(2) ?: ''; $field = $page->fields->get($fieldName); if(($field instanceof Field && $field->type == "FieldtypeDatetime") || $fieldName == "created" || $fieldName == "modified"){ $function = strpos($dateFormat, "%") !== false ? 'strftime' : 'date'; $raw = $page->getUnformatted($fieldName); return $event->return = $raw ? $function($dateFormat, $raw) : $empty; } }); It allows you to use this on datetime fields, no matter of the field settings: // date() syntax // => 04.02.2016 $page->getDate('zeit', 'd.m.Y'); // strftime syntax // => 4 Februar 2016 $page->getDate('zeit', '%e %B %Y'); // empty field value // => Nicht terminiert. $page->getDate('empty_zeit', '%e %B %Y', 'Nicht terminiert.'); // invalid field // => null $page->getDate('ziet', 'd.m.Y');3 points
-
Another proof-of-concept module: JsonNativeField Leverages MySQL >= 5.7.8's native JSON column type for key-value storage. This gives us the opportunity to store arbitrary (textual) fields in the database and allows us to search for them with plain subfield selector syntax, including wildcard operators. Possible applications are storing submitted form data or adding user-defined properties to their profile. Currently, the module is still really, really alpha, but I wanted to get input early on. Let me know what you think. Download from GitHub. Here are a few screenshots for anybody interested but unable to try for themselves: 1. First page with json field and custom subfields: 2. Second page with json field and custom subfields: 3. Searching through all subfields in the json field: 4. Searching only in a specific subfield: The interface is really rather crude still. The "delete" buttons only work after saving (have to attach listeners to the newly created entries yet), and I've got to straighten out supported operators for Lister to pick up. I'll see if I find some time tomorrow to work on these issues and brush up the visual side a bit.2 points
-
A PageTable field will not normally output a hidden page either. See here. But you can use getUnformatted() to get unpublished or hidden pages. $result = $page->getUnformatted('my_pagetable_field')[0]; //or $result = $page->getUnformatted('my_pagetable_field')->first();2 points
-
@Macrura Here's what's above the PW directives in my .htaccess. Notice that I'm pointing explicitly to a 403 html file, right below the 6G directives: ErrorDocument 403 /403.html Start of .htaccess: # 6G FIREWALL/BLACKLIST # @ https://perishablepress.com/6g/ # 6G:[QUERY STRINGS] <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{QUERY_STRING} (eval\() [NC,OR] RewriteCond %{QUERY_STRING} (127\.0\.0\.1) [NC,OR] RewriteCond %{QUERY_STRING} ([a-z0-9]{2000}) [NC,OR] RewriteCond %{QUERY_STRING} (javascript:)(.*)(;) [NC,OR] RewriteCond %{QUERY_STRING} (base64_encode)(.*)(\() [NC,OR] RewriteCond %{QUERY_STRING} (GLOBALS|REQUEST)(=|\[|%) [NC,OR] RewriteCond %{QUERY_STRING} (<|%3C)(.*)script(.*)(>|%3) [NC,OR] RewriteCond %{QUERY_STRING} (\\|\.\.\.|\.\./|~|`|<|>|\|) [NC,OR] RewriteCond %{QUERY_STRING} (boot\.ini|etc/passwd|self/environ) [NC,OR] RewriteCond %{QUERY_STRING} (thumbs?(_editor|open)?|tim(thumb)?)\.php [NC,OR] RewriteCond %{QUERY_STRING} (\'|\")(.*)(drop|insert|md5|select|union) [NC] RewriteRule .* - [F] </IfModule> # 6G:[REQUEST METHOD] <IfModule mod_rewrite.c> RewriteCond %{REQUEST_METHOD} ^(connect|debug|delete|move|put|trace|track) [NC] RewriteRule .* - [F] </IfModule> # 6G:[REFERRERS] <IfModule mod_rewrite.c> RewriteCond %{HTTP_REFERER} ([a-z0-9]{2000}) [NC,OR] RewriteCond %{HTTP_REFERER} (semalt.com|todaperfeita) [NC] RewriteRule .* - [F] </IfModule> # 6G:[REQUEST STRINGS] <IfModule mod_alias.c> RedirectMatch 403 (?i)(wp-admin|wp-content|wp-login) RedirectMatch 403 (?i)([a-z0-9]{2000}) RedirectMatch 403 (?i)(https?|ftp|php):/ RedirectMatch 403 (?i)(base64_encode)(.*)(\() RedirectMatch 403 (?i)(=\\\'|=\\%27|/\\\'/?)\. RedirectMatch 403 (?i)/(\$(\&)?|\*|\"|\.|,|&|&?)/?$ RedirectMatch 403 (?i)(\{0\}|\(/\(|\.\.\.|\+\+\+|\\\"\\\") RedirectMatch 403 (?i)(~|`|<|>|:|;|,|%|\\|\s|\{|\}|\[|\]|\|) RedirectMatch 403 (?i)/(=|\$&|_mm|cgi-|etc/passwd|muieblack) RedirectMatch 403 (?i)(&pws=0|_vti_|\(null\)|\{\$itemURL\}|echo(.*)kae|etc/passwd|eval\(|self/environ) RedirectMatch 403 (?i)\.(aspx?|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rar|rdf)$ RedirectMatch 403 (?i)/(^$|(wp-)?config|mobiquo|phpinfo|shell|sqlpatch|thumb|thumb_editor|thumbopen|timthumb|webshell)\.php </IfModule> # 6G:[USER AGENTS] <IfModule mod_setenvif.c> SetEnvIfNoCase User-Agent ([a-z0-9]{2000}) bad_bot SetEnvIfNoCase User-Agent (archive.org|binlar|casper|checkpriv|choppy|clshttp|cmsworld|diavol|dotbot|extract|feedfinder|flicky|g00g1e|harvest|heritrix|httrack|kmccrew|loader|miner|nikto|nutch|planetwork|postrank|purebot|pycurl|python|seekerspider|siclab|skygrid|sqlmap|sucker|turnit|vikspider|winhttp|xxxyy|youda|zmeu|zune) bad_bot # Apache < 2.3 <IfModule !mod_authz_core.c> Order Allow,Deny Allow from all Deny from env=bad_bot </IfModule> # Apache >= 2.3 <IfModule mod_authz_core.c> <RequireAll> Require all Granted Require not env bad_bot </RequireAll> </IfModule> </IfModule> ErrorDocument 403 /403.html <FilesMatch "\.(js|css|html|htm|php|svg)$"> SetOutputFilter DEFLATE </FilesMatch> <ifModule mod_headers.c> Header set Connection keep-alive </ifModule> # ---------------------------------------------------------------------- # Expires headers (for better cache control) # ---------------------------------------------------------------------- <IfModule mod_expires.c> ExpiresActive on # Your document html ExpiresByType text/html "access plus 0 seconds" # Data ExpiresByType text/xml "access plus 0 seconds" ExpiresByType application/xml "access plus 0 seconds" ExpiresByType application/json "access plus 0 seconds" # Favicon (cannot be renamed) ExpiresByType image/x-icon "access plus 5 days" # Media: images, video, audio ExpiresByType image/gif "access plus 1 week" ExpiresByType image/png "access plus 1 week" ExpiresByType image/jpeg "access plus 1 week" ExpiresByType image/webp "access plus 1 week" ExpiresByType image/svg+xml "access plus 1 week" # HTC files (css3pie) ExpiresByType text/x-component "access plus 1 month" # Webfonts ExpiresByType application/x-font-ttf "access plus 1 month" ExpiresByType font/opentype "access plus 1 month" ExpiresByType application/x-font-woff "access plus 1 month" ExpiresByType application/vnd.ms-fontobject "access plus 1 month" # CSS and JavaScript ExpiresByType text/css "access plus 1 week" ExpiresByType application/x-javascript "access plus 1 week" </IfModule> ################################################################################################# # START PROCESSWIRE HTACCESS DIRECTIVES # @version 3.0 # @indexVersion 300 ################################################################################################# ....2 points
-
It all make sense now! Thank you for guys for clarification.2 points
-
The images field by default does return a list of images and you cannot call size() on a list, but only on a single image. By using the settings of the field you can alter that behavior to only return a single image directly.2 points
-
I don't think so, no. The idea above was to replace any embedded ASCII carriage-return+linefeed pairs with a literal sequence '\' + 'r' + '\' + 'n' on save of the data. On reading the data the, now-literal, sequence is turned back into an embedded ASCII pair. If the ASCII linefeed and return characters can occur anywhere - not just next to each other - then you need to replace them individually. Try doing this instead... protected function encodeData($data) { $data = serialize($data); $data = str_replace("\r", '\r', $data); $data = str_replace("\n", '\n', $data); return $data; } protected function decodeData($data) { $data = str_replace('\r', "\r", $data); $data = str_replace('\n', "\n", $data); $data = unserialize($data); return $data; } public function addItem($arrayData) { if(!$this->_addItem()) return false; if(2 != $this->getState()) return false; if(!$fp = @fopen($this->getFilename(), 'ab')) return false; if(flock($fp, LOCK_EX)) { $data = $this->encodeData($arrayData) . "\n"; $res = fwrite($fp, $data); fflush($fp); flock($fp, LOCK_UN); fclose($fp); return $res == strlen($data); } fclose($fp); return false; } public function getItem($worker = null) { if(!$this->_getItem()) return false; if(2 != $this->getState()) return false; if(!$fp = @fopen($this->getFilename(), 'rb+')) return false; if(flock($fp, LOCK_EX)) { $line = trim(fgets($fp)); if(!$line) { flock($fp, LOCK_UN); fclose($fp); if(0 == $this->itemCount()) return null; return false; } // we have the first entry, now write all following data into a buffer $fpTmp = @fopen('php://temp/maxmemory:' . intval(1024 * 1024 * 5), 'rb+'); while(!feof($fp)) fwrite($fpTmp, fread($fp, 4096)); fseek($fp, 0, SEEK_SET); ftruncate($fp, 0); fseek($fpTmp, 0, SEEK_SET); // write back buffer into file while(!feof($fpTmp)) fwrite($fp, fread($fpTmp, 4096)); fclose($fpTmp); fflush($fp); flock($fp, LOCK_UN); fclose($fp); } return $this->decodeData($line); } Sorry, I don't really have time to test this out - you'll have to play with the encoding. You may find that doing the serialisation at the end of the encode (and unserialisation at the start of decode) might do it. HTH2 points
-
In this case, Google recommends just in the head, or after the opening body tag:2 points
-
I thought about this feature as well from time to time . There is a new version 1.0.1 which fixes some PHP7 issues and adds the possibility to set custom labels for each extra field. It also supports multi-language usage. Furthermore I changed the way the extra fields (form) are rendered. Now you can click a tab and briefly hold (aka long-click) it and all extra fields will switch to that language. And I removed the checkbox for the caption field. If it was set, it will be added as first item in the `other fields` input field.2 points
-
This module allows the page name to change when the title is edited. Modules directory: http://modules.processwire.com/modules/page-rename-options/ Github: https://github.com/adrianbj/PageRenameOptions I'd love to think that this module was not necessary for me but, especially during development, I find that page titles often change and I'd really rather have the names/urls match the title. I don't think you can expect clients to remember to change the name when they change the title, or even if they do, they still have to get it right which can be a challenge with a long article names with characters not allowed in page names. With none of the config settings checked, the default behavior is to have the page name always match changes to the page title, but allow the user to manually edit if they want. The options allow you to protect initial differences (changes you may have made as a user with an exempt role), completely disable manual changes, or protect manual name changes from subsequent changes to the title while editing. My preferred settings are to set the exempt role as superuser, and check "Initial Differences Protected" and "Prevent Manual Changes". CONFIG SETTINGS Exempt Roles The selected roles will not be subject to any of the rules below. The name will change automatically with the title, but they will be able to manually edit the page name as desired. Excluded Pages Pages that are excluded from the actions of this module. Changing the titles of selected pages will behave as though this module is not installed. For multi-language sites it is recommended to select the site's homepage. Initial Differences Protected If checked, further changes to the name (to match a changing title) will not happen if the name is already different from the title (evaluated on page edit initial load) Prevent Manual Changes If checked, it won't be possible to manually edit the name. If checked, this will disable the "Live Changes Protected" setting since it won't be possible to make any manual changes. Live Changes Protected If checked, further changes to the name (to match a changing title) will not happen if the name field was manually changed at any time during the current page edit. Please test the behavior of each setting thoroughly so you understand what each one does! Please let me know if you have any further requirements around permissions / role access to the module's functionality.1 point
-
I have been using this module for a long time and it's been incredibly useful so I thought it was time to share. It's great for fields where you want to instruct content creators to reference something about a the page, its template, or its parent, or grand parent, etc Specify fields/properties of the page in your field's Description or Notes content, eg: [page.parent.url] [page.title] [page.template.label] You can also define a str_replace to be performed on the returned value, eg: [page.name.(-|_)] which will return the page name with the dashes replaced with underscores. An option to allow raw HTML is available. You can also use hanna codes within your description and notes fields - big thanks to @Robin S for this idea. http://modules.processwire.com/modules/dynamic-description-notes/ https://github.com/adrianbj/DynamicDescriptionNotes/ Hope you find it useful.1 point
-
This basic tutorial is primarily aimed at those new to PW. It could also serve as a reference to others more seasoned PW users. The question about how to categorise content comes up in the forums now and again. Hopefully with this post we’ll have a reference to guide us right here in the tutorials board. Many times we need to organise our site content into various categories in order to make better sense of the data or to logically and easily access it. So, how do you organise your data when you need to use categories? Here are a few tips gathered from the PW forums on how to go about this. Using these tips will, hopefully, help you avoid repeating yourself in your code and site content and keep things simple. See the links at the end of this post to some useful discussion around the topic of categorisation. Before making decisions about how to organise your site, you need to consider at least three questions: What items on my site are the main items of interest? These could be people or things (cars, plants, etc.). In most cases, these are the most important content on which all the other stuff point to. Where do items need to be grouped into categories? This is about where items need to “live”. It is about the attributes of the items of interest (e.g. responsibilities, job types, colour, etc.). Attributes can have sub-attributes (e.g. a category job type = driver could be further sub-classified as job type role = train driver). Can they live in more than one place? - This is about having multiple attributes. There could be other issues such as the type of content your main items of interest are but that’s for another post. We’ll keep these examples simple. The main principles explained below still apply. There are at least three possible ways in which you can organise your content depending on your answers to the above three questions. These are: Single category Simple multiple categories Complex multiple categories These are illustrated below. Note that this is what I call them; these are not PW terms. 1. Single Category Suppose you need to do a site for a company that’s made up of several Departments each with employees performing unique functions. These could include “Finance”; “Media Communications”; “Administration”; “Technicians”; “Human Resources”; “Logistics”. We ask ourselves the following questions based on our 3 questions above: 1. Q: What items on my site are the main items of interest? A: Employees. 2. Q: What attributes of our items of interests are we interested in? A: Departments. (Single main category) 3. Do the Departments have sub-categories? A: Yes. (Multiple sub-categories) 4.Can Employees belong to multiple sub-categories? A: No. (Single sub-category) We conclude that what we need is a Single Category model. Why? This is because, in Single Categories model, items of interest can only belong to 1 and only 1 main/parent category and within that only 1 sub-category Employees in this company can only belong to one and only one department. Finance guys do their finance and Logistics guys do their stuff. Letting Techies do press conferences is probably not going to work; that we leave to the Media guys . Assuming the company has the following employees - James, John, Mary, Ahmed, Peter, Jason, Barbara etc., arranging our site content to fit this model could look like the following: Items of interest = Employees Categories = Departments Adopting out strategy to keep it simple and logical, let us write down, hierarchically, our employee names against their departments to mimic the PW tree like this: James Finance John Finance Mary Technician Ahmed Logistics Barbara Media Etc. We notice, of course, that departments start repeating. It doesn't look like we are doing this very logically. If we think about this carefully, we will conclude that, naturally, the thing (attribute in this case) that keeps repeating should be the main criteria for our categorisation. This may seem obvious, but it is worth pointing out. Also, remember, that as per the responses to our questions, the categories (Finance, Logistics, etc.) do not have sub-categories. In this aspect, we are OK. Using this principle about repeating attributes, we find that Departments, rather than Employees, need to be the main categories. Hence, we categorise our PW site content by doing the following. Create a template for each Department. Hence, we have a template called Finance, Logistics, etc. Add the fields needed to those templates. This could be a text field for holding Employee phone numbers, email field for email, title field for their names, etc. Create top level pages for each Department and assign to them their respective templates. Give them appropriate titles, e.g., Finance, Media, etc. Create a page for each employee as a child page of the Department which they belong to. Give them appropriate titles, e.g. James, John, etc. We end up with a tree that looks like this: 1. Finance (ex. main category) a. James (ex. item of interest) b. John c. Shah d. Anne 2. Logistics (ex. main category) a. Ahmed b. Matthew c. Robert d. Cynthia 3. Media a. Barbara b. Jason c. Danita 4. Human Resources a. Michael b. Pedro c. Sally 5. Technician a. Mary b. Oswald c. Dmitri d. Osiris Since an employee can only belong to one Department, our work here is done. We can then use PW variables, e.g. $page->find, $pages->find with the appropriate selectors to find employees within a Department. This is a very basic example, of course, but you get the idea. You have the choice of creating one template file for each category template as well. I prefer the method of using one main template file (see this thread). You could do that and have all Departments use different templates but a single template file. In the template file you can include code to pull in, for example, the file “technician.inc” to display the relevant content when pages using the template “Technician” are viewed. Example code to access and show content in Single Categories model $hr = $pages->find("template=human-resources, limit 50"); foreach ($hr as $h) { echo "{$h->title}"; } But sites do not always lend themselves to this model. Many times, items of interest will need to belong to multiple categories. 2. Simple Multiple Categories Let’s say you were building a site for cars - red cars, blue cars, 2-seaters, 5-seaters, etc. Again, we ask ourselves our questions based on our initial three questions: 1. Q: What items on my site are the main items of interest? A: Cars. 2. Q: What attributes of our items of interests are we interested in? A: Colour, Number of seats, Models, Year of manufacture, Types. (Multiple categories) 3. Do these multiple attributes have sub-attributes? A: Yes. e.g., the attribute Colour has several sub-categories - red, white, green, etc. (Multiple sub-categories) 4. Can Cars have multiple sub-attributes? A: No. e.g., a yellow car cannot be a green car. (Single sub-categories) We therefore conclude that what we need is a Simple Multiple Category model. Why? This is because, in Simple Multiple Categories, items of interest can belong to multiple parent categories. However, within those parent categories, they can only belong to one sub-category. Assuming we have the following cars, manufactured between 2005 and 2008, as items of interest: Mercedes, Volvo, Ford, Subaru, Toyota, Nissan, Peugeot, Renault, Mazda, arranging our site content to fit this model could look like the following: Items of interest = Cars Categories = Model, Year, Colour, Number of seats, Type Sub Categories = Model [Prius, etc.]; Year [2005, 2006, 2007, 2008]; Colour [Red, Silver, Black, White, Green]; Number of seats [2, 5, 7]; Types [sports, SUV, MPV]. Adopting out strategy to keep it simple and logical, if we wrote down our cars names against their attributes like this: Mercedes Model-Name: Year: 2005 Colour: Silver Seats: 2-seater Type: Sports Volvo Model-Name: Year: 2007 Colour: Green Seats: 5-seater Type: SUV Ford Model-Name: Year: 2007 Colour: Red Seats: 7-seater Type: MPV Etc We notice, again, that car attributes start repeating. In order not to repeat ourselves, we want to avoid the situation where our child pages “names” keep repeating. For instance, in the above example tree, we want to avoid repeating year, colour, etc. within the tree. Of course in the frontend our output needs to look like the above where we can list our cars and their respective attributes. We just don’t need a tree that looks like this in the backend. Since we have multiple categories and sub-categories, we need to rethink our strategy for categorising our content as illustrated below. The strategy we used in the first category model will not work well here. Hence, these repeating attributes (year, colour, etc.) need to be the main criteria for our categorisation. We need to end up with a tree that looks like this: 1. Cars a. Mercedes (ex. item of interest) b. Volvo c. Ford d. Subaru e. Toyota f. Range Rover g. Peugeot h. Renault i. Mazda 2. Model (ex. main category) a. Fiesta (ex. sub-category) b. Miata c. Impreza d. Matrix e. Prius f. E-Class g. XC-90 h. Scenic i. L322 j. 505 3. Year a. 2005 b. 2006 c. 2007 (ex. sub-category) d. 2008 4. Colour a. Red b. Silver c. Black d. White e. Green 5. Number of Seats a. 2 b. 5 c. 7 6. Type a. MPV b. Sports c. SUV d. Other At the top of the tree, we have our main items of interest, Cars. They do not have to come first on top of the tree like that but it just makes sense to have them like this. Next, we have the Cars’ categories (attributes). The main categories are parent pages. Each main category has children which act as its sub-categories (cars’ sub-attributes). For instance, the main category colour has sub-categories “red”, “green”, etc. Grouping them under their main category like this makes better sense than having them dangling all over the tree as parent pages themselves. Now that we know what we want to achieve, the next question is how do we go about relating our categories and sub-categories to our main items of interest, i.e., cars? Fields come to mind. OK, yes, but what about the sub-categories (2006, red, 5-seater, etc.)? Surely, we can’t keep typing those in text fields! Of course not; this is PW. We like to simplify tasks as much as we can. What we need is a special type of field. Page Reference Fields or Page Fieldtypes add the ability to reference other pages, either single or multiple pages, within a page. For instance, we could have a Page Reference Field in the template that our Car pages use. Let’s call this “car-template”. When viewing Car pages, we would have the ability to select other pages on our site that we wish to reference, for instance, because they are related to the page we are viewing. In other cases, we could also wish to reference other pages that contain attributes/values of the page we are viewing. This is the situation with our Cars example above. Hence, the sub-categories/sub-attributes for our Cars will be pulled into our car pages using Page Reference Fields. There are two types of Page Reference Fields; single page and multiple pages. What each do is obvious from their names. Single Page Reference Fields will only reference one page at a time. Multiple Page Reference Fields will reference multiple pages. OK, let’s go back to the issue at hand. We need to categorise Cars by various attributes. Do we need to reference the main categories (Year, Type, etc.) in our Car pages? In fact, we don’t. What we need to reference are the sub-categories, i.e. 2005, red, SUV, etc. These will provide the actual attributes regarding the parent attribute of the Cars. We have said we do not wish to type these sub-categories/attributes all the time hence we use Page Reference Fields. Which type of Page Reference Field should we use? Remember that our Cars can have only one sub-category/sub-attribute. That’s our cue right there. In order to select one and only one sub-attribute per Car, we need to use the single Page Reference Field. Hence, we categorise our Cars PW site by doing the following (you may follow a different order of tasks if you wish). Create a template to be used by the Car pages. Give it a name such as car-template Create a page for each of your cars and make them use the car-template Create one template to be used by all the main attribute/categories and their children (the sub-categories). We do not need a template for each of the categories/sub-categories. I name my template “car-attributes” Of course you can name yours differently if you wish. Add the fields needed to this template. You don’t need anything other than a title field for each actually. Create top level pages for each main category and assign to them the template car-attributes. As before, give your pages meaningful titles. Do the same respectively for their child pages. E.g., you should have the following child pages under the parent “Year” - 2005, 2006, 2007 and 2008. Create the Page Reference Fields for each of your main categories/parent attributes. Using our example, you should end up with 5 Page Reference Fields (model, year, colour, seats and type). Each of these should be single Page Reference Fields. It’s a good idea, under the BASICS settings while editing the fields, to include some Description text to, include additional info about the field, e.g. instructions. In addition, you don’t want any page that doesn't belong to a particular attribute to be selectable using any of the Page Reference Fields. For instance, when referencing the year a car was manufactured, we want to be able to only select children of the page Year since that is where the year sub-categories are. We do not want to be able to select children of Colour (red, green, etc.) as the year a car was manufactured! How do we go about this? PW makes this very easy. Once you have created your Page Reference Fields, while still in the editing field mode, look under the settings INPUT. The fourth option down that page is “Selectable Pages”. Its first child option is “Parent of selectable page(s)”. Where it says “Select the parent of the pages that are selectable” click on change to change the parent. By now you know where I am going with this. For the Page Reference Field named Year, choose the page “Year” as the parent whose children will be selectable when using that Page Reference Field to select pages. Similarly, do this for the remaining 4 Page Reference Fields. Note that under this field settings INPUT you can change how you want your pages to be selectable. Be careful that you only select the types that match single Page Reference Fields, i.e. the ones WITHOUT *. For single Page Reference Fields, you have the choices:Select - a drop down select Radio buttons PageListSelect Now edit the car-template to add all 5 of your Car Page Reference Fields. We are now ready to roll. Go ahead and edit your Car pages. In each of them you will see your 5 Page Reference Fields. If you followed the instructions correctly, each of them should only have the relevant child pages/sub-attributes as selectable. Do your edits - select year when car was manufactured, its colour, type, number of seats, etc. and hit Save. By the way, note that Page Reference Fields give you access to all the fields and properties of the page being referenced! You have access to the referenced page’s title, name, path, children, template name, page reference fields, etc. This is really useful when creating complex sites. I call it going down the rabbit hole! These properties of the referenced page are available to you on request. It does mean that you will have to specifically echo out the property you want from that page. Page Reference Fields are echoed out like any other field. Example code to access and show content in Simple Multiple Categories model $cars = $pages->find("template=car-template, limit=10, colour=red, year=2006, seats=5"); foreach ($cars as $car) { echo $car->title; echo $car->year; echo $car->colour; } I have made the above verbose so you can easily follow what I'm trying to achieve. The above code will find 10 red 5-seater cars manufactured in 2006. Remember, colour, year and seats are the names of your custom Page Reference Fields that you created earlier. Some sites will have content that belong to multiple categories and multiple sub-categories. We address this below. 3. Complex Multiple Categories Suppose you are developing a site for a school. The school has teachers (duh!) some of whom teach more than one subject. Besides their classroom duties, some teachers are active in various clubs. On the administration side, some teachers are involved in various committees. You know the drill by now. Let’s deal with our basic questions. 1. Q: What items on my site are the main items of interest? A: Teachers. 2. Q: What attributes of our items of interest are we interested in? A: Subjects, Administration, Clubs (Multiple categories) 3. Do these multiple attributes have sub-attributes? A: Yes. e.g., the attribute Subjects has several sub-categories - History, Maths, Chemistry, Physics, Geography, English, etc. (Multiple sub-categories) 4. Can Teachers have multiple sub-attributes? A: Yes. e.g., a Teacher who teaches both maths and chemistry (Multiple sub-categories) Apart from the response to the final question, the other responses are identical to our previous model, i.e. the Simple Multiple Categories. We already know how to deal with multiple categories so we’ll skip some of the steps we followed in the previous example. Since our items of interest (Teachers) can belong to more than one sub-category, we conclude that what we need is a Complex Multiple Category model. In Complex Multiple Categories, items of interest can belong to multiple parent categories and multiple sub-categories both within and without main/parent categories. By now we should know what will be the main criteria for our categorisation. We need to end up with a tree that looks like this: 1. Teachers a. Mr Smith (ex. item of interest) b. Mrs Wesley c. Ms Rodriguez d. Mr Peres e. Mr Jane f. Mrs Potter g. Ms Graham h. Mrs Basket i. Dr Cooper 2. Subjects (ex. main category) a. History (ex. sub-category) b. Maths c. English d. Physics e. Chemistry f. Geography g. Religion h. Biology i. French j. Music 3. Clubs a. Basketball b. Debate c. Football d. Scouts e. Sailing f. Writing 4. Administration a. Discipline b. Counselling c. Exams board d. Public relations e. Education We are ready to build our site. Which type of Page Reference Field should we use? Remember that our Teachers can teach more than one subject and can be involved in various sub-category activities. That’s our cue right there. In order to select multiple attributes/categories, we of course go for the multiple Page Reference Field. Similar to the previous example, create necessary templates and fields for the site. For our multiple Page Reference Fields, remember to select the correct input field types. These should match multiple Page Reference Fields and are marked with *. For multiple Page Reference Fields, the available choices are: Select Multiple* AsmSelect* Checkboxes* PageListSelectMultiple* PageAutoComplete* Remember to add the multiple Page Reference Fields to the Teachers template. Go ahead and test different selectors, e.g. find Teachers that teach Maths and Chemistry and are involved in the Writing club. Whether you get results or not depends on whether there is actually that combination. An important point to remember is that your multiple Page Reference Fields will return an array of pages. You will need to traverse them using foreach (or similar). Example code Complex Multiple Categories model Find the subjects taught by the Teacher whose page we are currently viewing. You can use if statements to only show results if a result is found. In this case, of course we expect a result to be found; if a Teacher doesn't teach any subject, he/she has no business teaching! subjects is the name of one of your custom Multiple Page Reference Fields. echo "<ul>"; foreach ($page->subjects as $x) { echo "<li>{$x->title}</li>"; } echo "</ul>"; There will be situations where you will need to use both Single and Multiple Page Reference Fields (independently, of course). For instance, in our Teachers example, we might be interested in the Gender of the Teacher. That would require a Single Page Reference Field. Summary What we have learnt: Categorising our site content need not be a nightmare if we carefully think it through. Of course not all sites will fit neatly into the 3 models discussed. By providing answers to a few simple key questions, we will be able to quickly arrive at a decision on how to categorise our content. There are at least 3 models we can adopt to categorise our content - single category; simple multiple category; and complex multiple category. In the latter two models, we make full use of PW’s powerful Page Reference Fields to mimic a relational database enabling us to roll out complex sites fast and easy. Useful links: http://processwire.com/talk/topic/3553-handling-categories-on-a-product-catalogue/ http://processwire.com/videos/create-new-page-references/ http://processwire.com/videos/page-fieldtype/ http://processwire.com/talk/topic/1041-raydale-multimedia-a-case-study/ http://processwire.com/talk/topic/683-page-content-within-another-page/ http://processwire.com/talk/topic/2780-displaying-products-category-wise/ http://processwire.com/talk/topic/1916-another-categories-question/ http://processwire.com/talk/topic/2802-how-would-you-build-a-daily-newspaper/ http://processwire.com/talk/topic/2519-nested-categories/ http://processwire.com/talk/topic/71-categorizingtagging-content/ http://processwire.com/talk/topic/2309-best-way-to-organize-categories-in-this-case/ http://processwire.com/talk/topic/2200-related-pages/ http://processwire.com/talk/topic/64-how-do-you-call-data-from-a-page-or-pages-into-another-page/1 point
-
We had to add this to our latest project and I am happy to share here. I couldn't find anything on the forums for this so apologies if it has been done before. But there are always different ways of doing things: $firstEntry = $pages->find("parent_id=1037, sort=date_1, limit=1"); foreach (range(date("Y"), date("Y", $pages->get("$firstEntry")->date_1)) as $year) { $start = strtotime(date("$year-01-01")); $end = strtotime(date("$year-12-31")); $count = $pages->count("parent_id=1037, date_1>=$start, date_1<=$end"); if ($count > 0) echo '<li><a href="' . $page->parent->url . $year . '/">' . $year . '(' . $count . ')</a></li>'; } So what is going on: first of all, our pages were children, so we set the parent_id, and our date field is called date_1 we need to get the year of the oldest entry, so that happens with $firstEntry and a simple find next we create an array using a range of years, we start with the current year, then we get the year from our $firstEntry (note: if you have an output format for your date set in the field settings you will want to use $pages->get("$firstEntry")->getUnformatted("date_1") within the foreach) next we create a start date and end date for the year we count if there are any entries for that year if there are display them in a list Your next step would be to create the $input->urlSegment code to display your pages.1 point
-
@szabesz - I had a play around to see how you could use custom PHP replacements in the description field. My first thought was create a module where you define tag/code pairs in the module config, then look for and replace those in descriptions. This works, but requires the use of eval() and conventional wisdom is that eval() is evil. So my next thought was Hanna Code, and this seems to work great. In ready.php (or create an autoload module): $this->addHookBefore('Inputfield::render', function($event) { if(!$this->wire('modules')->isInstalled('TextformatterHannaCode')) return; if(!($this->wire('process') && $this->wire('process')->className() == 'ProcessPageEdit')) return; $inputfield = $event->object; $description = $inputfield->description; if($description == '') return; $this->wire('modules')->TextformatterHannaCode->formatValue(new Page(), new Field(), $description); $inputfield->description = $description; }); Then set up the Hanna codes you want to use in description fields. If you want to get the page object for the page being edited then add this at the top of your Hanna code... if($process && $process->className() == 'ProcessPageEdit') { $p = $process->getPage(); } else { return "[Hanna code '$hanna->name' is not valid for this field]"; } return $p->url; // an example to return the URL to the page without scheme and hostname ...then access the page object as $p1 point
-
Is your CKEditor inputfield set to less than 100% width? Or in a fieldset that is less than 100% width? If so the culprit is probably the height spacer JS. GitHub issue here, has never been completely fixed. Only solution for me is never set CKEditor field at less than 100% width.1 point
-
Indeed! My favorite: “...just wait for it, we are going to do assembly in the web in a year or two." I just can't wait1 point
-
In case anyone finds this thread because they're deploying a project started in PW2.7 or older to a ServerPilot-managed container (in which case, just updating the schema isn't sufficient, as many records may have been created with invalid values), ServerPilot recommends creating a separate .cnf file to disable sql strict mode: https://serverpilot.io/community/articles/how-to-disable-strict-mode-in-mysql-5-7.html Don't just copy and paste that configuration, though. The specific items that need to be removed are NO_ZERO_IN_DATE and NO_ZERO_DATE. Creating a separate .cnf file for your customizations will avoid them being overwritten by automated ServerPilot updates.1 point
-
That should be all you need. Please try it out and see for yourself.1 point
-
Do you really need to unpublish the page? Why not just hide it?1 point
-
Welcome to the ProcessWire Frorum @leegold a Step by step tutorial: http://blog.mauriziobonani.com/tags/#processwire Basic ProcessWire website workflow - Part Four Basic ProcessWire website workflow - Part Three Basic ProcessWire website workflow - Part Two Basic ProcessWire website workflow - Part One1 point
-
Thanks Adrian! It was just an idea I wanted to share but not really a feature request or so. And also thanks for reminding me of the RuntimeMarkup module!1 point
-
1 point
-
Is image_single set to a max of 1 image on the details tab?1 point
-
Ah I understand now, I hadn't realized single quotes were used for literal strings. All makes sense and the above code seems to do the trick, thanks once again!1 point
-
thanks for correcting me; i was going by what I've seen on the majority of sites, as well as the HTML5 boilerplate, so i was blindly following the crowd, and i think google changed their instructions at some point also.1 point
-
1 point
-
@LostKobrakai Oh, you're right, of course. Stroked! It doesn't work only when you call a function directly: function greet() { return 'Hi!'; } echo "Trigger greeter: {greet()}"; // Trigger greeter: {greet()}1 point
-
Hey Beat, no need to bang your head If you didn't change the output in the field settings, you should be getting a timestamp (1475743564). You can just break it down into date and time like this: echo "<p>Datum: " . strftime( '%d/%m/%Y', $event->zeit ); echo "<br />Zeit: " . strftime( '%H:%M:%S', $event->zeit ); The strings that I'm passing to the function are time representations from this list: http://php.net/manual/en/function.strftime.php You can do something more elaborate like this: strftime( '%A, %e of %B of the year %Y', $event->zeit ); which would output "Thursday, 6 of October of the year 2016" In that case, you would probably want to output them in German, so you have to set the locale if the system isn't already: setlocale(LC_ALL, "de_CH", "de_CH.utf-8", german") strftime( '%A, %e of %B of the year %Y', $event->zeit );1 point
-
Yes I do. You'd only have to pay the difference. You'd have to send me an email to arrange that. Thanks.1 point
-
Hi @Robin S, Just acknowledging that I've seen this. Really pressed for time currently but would like to give a comprehensive answer, so hope you can wait a bit longer? In summary though, I think I might be able to add some of the features you've suggested (though some might take a while...a long while to implement). My biggest constraint is time (cliche, I know) though,...not lack of willingness .1 point
-
I don't think that this has something to do with the change of the regex engine. The source code contains in one case single quotes in the other one double quotes. While writing the regex I thought about adding a check for double or single quotes - either way, the code now checks both occurrences, so it doesn't matter if the html contains single or double quotes. You can see it here: https://regex101.com/r/emj9Ie/11 point
-
Welcome to the forums, @leegold ! I think you're going to like the tutorials by @benbyf, published on https://tutsplus.com/authors/ben-byford1 point
-
Also check your error logs and look for the image on the server, if it's there check the permissions and ownership.1 point
-
1 point
-
You're right. The check whether to show the description label or not missed a condition. Since adding the opportunity to add textformatters I changed InputfieldText to InputfieldTextarea. Textformatters like Newlines to Unordered List doesn't make that much sense if you aren't able to add line breaks. I added a condition: all fields default to InputfieldText except the fields which got a textformatter assigned. I'm not that happy with the layout/styles right now. I need to invest some more time optimizing the layout. You're right, too. I missed the following scenario: checked captionField but added no otherField. The fixes are merged into the master branch1 point
-
Unexpectedly found a half day to spare, so I've pushed 0.0.3 to GitHub. New features: Field settings for custom date, date+time and text fields can now be made on the inputfield's input tab, e.g. date and time formats, placeholder text or text validatoin patterns (numeric field settings are on the todo list) Names for custom fields are limited to start and end with ASCII letters and only have alphanumeric ASCII characters and hyphens in between Custom field name of "data" is silently stripped to avoid bollixing up all entries The custom fields table in the backend is now sorted by name (new entries simply get appended) The module is still alpha. Things are getting smoother, but there are still a few items on the todo list.1 point
-
Just a quick status update: I've started implementing different field types (text, integer, float, date, date+time) with native inputfields. Types can be switched back and forth, and I'll make it hookable so custom inputfields can be added as well. Will be a while though, since it looks like I'll be busy with a lot of other stuff until the end of next week. Here's a teaser though...1 point
-
Yeah, but that's just about it. Any module / template / field or other setting is saved in the db.1 point
-
Hi. Since PW 3.0.9 we have very useful long-click functionality in Lister. As small UI enhancement i would like to propose additional actions as "Save + Exit" while editing some page in modal. Now you have to make two clicks. First click "Save" and then click "Close", with "Save + Exit" it will be just one click.1 point
-
Not sure if this really belongs here, but interesting to see that: http://www.burgerking.it/ is running on PW and yet several other of their regional sites, eg: http://burgerking.ca/ are running Drupal. Sites looks very similar visually.1 point
-
Can you try the latest version on git? The error should be fixed with version 0.1.0. The latest version also incorporates @tpr's fix for the count() on null problem in case someone removes one of the fields from the MediaLibrary template. @Zeka: I'm still looking into script loading in the frontend question. Currently, it's expected behaviour for an uncoditional autoload module, but I'm of course looking to only have the script loaded when necessary. Might be a while though, as it means a lot of testing and delving through PW's frontend editing code until I know what I'm doing.1 point
-
can you try moving the page up to the top, in the admin page branch? sure, i can try, and the plan is to eventually make a module... but in the meantime i'll try and make a tutorial, because until the module is made, it's just a lot of fields, templates and pages in the admin; then 1 dashboard.php, and 3 css files1 point
-
Another update today! I noticed more and more people in the forums are using with the "Disable Settings Tab?" option (available via: $config->advanced = true). With this disabled, and if the "Display 'name' field in content tab?" setting is not enabled, the "Name" field is not available for javascript manipulation when the title is changed. This update checks for these two settings and if required it will change rename behavior to work on page save instead of instantly via javascript. This alternate method respects the "Initial Differences Protected" setting, but of course the "Prevent Manual Changes" and "Live Changes Protected" options are not relevant since it isn't possible to manually change the page name since the field is not available in the page edit dialog. This update is therefore only relevant if you are using that "Disable Settings Tab?" option, but if you are and you're using this module, please let me know if you have any problems.1 point
-
As a composer, the thing I MUST avoid is anything I have written, or anything written in a style that I like. The trouble is that I start picking holes in it and forget the work I am meant to be doing and end up writing music instead. So, inevitably I end up either sitting in silence or listening to Manuel & The Music of the Mountains or Pan Pipes - which is pretty much the same as silence, to be honest.1 point