Jump to content


Popular Content

Showing content with the highest reputation on 03/26/2018 in all areas

  1. 3 points
    @ethanbeyer Did you manage to work around the profile edit screen limitations? I have a directory site where users are the directory pages. Their profiles have lots of fields, including tabs andf repeaters. Since it was not possible to use the native profile edit process, I needed to find a workaround. I have a custom Dashboard page in the admin where users have a link to their user page edit screen URL like /access/users/edit/?id=1377 To have this profileEditUrl easily available for every user, I added it as a custom property via a hook: $this->addHookProperty('User(template=member)::profileEditUrl', $this, 'addPropertyProfileEditUrl'); /** * adds profile edit URL property to every member user * * @param HookEvent $event * */ public function addPropertyProfileEditUrl($event) { $user = $event->object; $event->return = $this->pages->get('template=admin, name=users')->url . "edit/?id={$user->id}"; } I had to give the member role page edit permissions for the member template. So I needed a way to make sure that they could not access other members' edit urls by just changing the id parameter in the URL. My hook for that looks like /** * prevent member user from editing other member pages */ $this->addHookAfter('ProcessPageEdit::loadPage', function(HookEvent $event) { $id = $event->arguments[0]; $user = $this->user; if($user->isSuperuser()) return; $editPage = $this->wire('pages')->get((int) $id); if($editPage->template != 'member') return; // normal members can only edit their own profile if($editPage->id != $user->id) wire('session')->redirect($user->profileEditUrl); }); Could also have hooked into Page::editable and apply logic there, I guess...
  2. 3 points
    It's a bit on the back burner right now. I was hoping for some more elaborate possibilities with MySQL 8, but the changes to JSON support there were on the homeopathic end rather than the dynamic typing support I had hoped for. I plan to brush up the UI and client side validation a bit once PW 3.1 gets out, though, and test things out in depth with UIkit admin theme.
  3. 2 points
    JavaScript, CSS and $this->wire('files')->render('your-file') in Runtime Markup code setting . 'your'file' has the PHP. See video demo below. Works on the fly, no need to save first + shows what's already saved. I do . See video demo. Another option is RM as suggested by @Sergio. See this quick demo. I can post the code later in RM's forum. Picture Options is a Select Options field. Options Illustration is a RuntimeMarkup Field.
  4. 2 points
    i do this with selectize, or with some js that updates the selected opt; requires an extended input with data attr for img src
  5. 2 points
    from @Robin S $this->addHookAfter('FieldtypeRepeater::wakeupValue', function($event) { $field = $event->arguments('field'); if($field->name !== 'myrepeater') return; // repeater field name $pa = $event->return; $pa->sort("-created"); // or whatever sort you want $event->return = $pa; }); Will return : 2018 2017 2016 ...
  6. 2 points
    Maybe this is versatile for your needs... Best regards mr-fan
  7. 2 points
    I think it would work. $files->($zip, array|string $files)
  8. 2 points
    Thanks @Robin S, I'll take a look at these ASAP. Part of the reason the new UI works as it does (in context, not overlay) is so that it could play nicely with some admin theme quirks and differences. Another reason is that overlay UI's are a bit of a problem from usability point of view, so I'd rather steer away from them. Anyway, I'll see what I can do about these. The part about checkbox is a bit of a surprise to me. This also means that other icons, such as the default "collapse" icon, disappear when the field gets expanded, right? Seems weird to me, but perhaps that's how it's supposed to work. Not sure how I managed to miss this earlier
  9. 2 points
    @gebeer Take a look at Ryan comment at this issue https://github.com/processwire/processwire-issues/issues/538
  10. 2 points
    Hi and welcome, In the following thread you can also find 3 nice videos to get started :
  11. 1 point
    Video or Social Post Embed Based on the TextformatterVideoEmbed module developed by Ryan Cramer, we have added the possibility to embed publications of the main social networks Facebook, Twitter and Instagram. ProcessWire Textformatter module that enables translation of YouTube, Vimeo, Instagram, Facebook, Twitter or Issuu URLs to full embed codes, resulting in a viewable video or social post in textarea fields you apply it to. How to install Download or Clone from Github: https://github.com/lexsanchez/VideoOrSocialPostEmbed Copy the VideoOrSocialPostEmbed.module file to your /site/modules/ directory (or place it in /site/modules/VideoOrSocialPostEmbed/). Click check for new modules in ProcessWire Admin Modules screen. Click install for the module labeled: "Video or Social Post Embed". Now you will be on the module config screen. Please make note of the config options and set as you see fit. How to use Edit your body field in Setup > Fields (or whatever field(s) you will be placing videos in). On the details tab, find the Text Formatters field and select "Video or Social Post Embed". Save. Edit a page using the field you edited and paste in YouTube, Vimeo, Facebook, Twitter, Instagram and/or Issuu URLs each on their own paragraph. Example How it might look in your editor (like TinyMCE): How it works This module uses YouTube, Vimeo, Instagram, Facebook, Twitter and Issuu oEmbed services to generate the embed codes populated in your content. After these services are queried the first time, the embed code is cached so that it doesn't need to be pulled again. Configuration You may want to update the max width and max height settings on the module's configuration screen. You should make these consistent with what is supported by your site design. If you change these max width / max height settings you may also want to check the box to clear cache, so that YouTube/Vimeo/Facebook/Twitter/Instagram/Issuu oembed services will generate new embed codes for you. Using with Markdown, Textile or other LML This text formatter is looking for a YouTube, Vimeo, Instagram, Facebook, Twitter or Issuu video URL surrounded by paragraph tags. As a result, if you are using Markdown or Textile (or something else like it) you want that text formatter to run before this one. That ensures that the expected paragraph tags will be present when VideoOrSocialPostEmbed runs. You can control the order that text formatters are run in by drag/drop sorting in the field editor. Copyright 2018 by Ryan Cramer / Updated by Lex Sanchez
  12. 1 point
    I've just added a pull request for a ProcessWire driver to laravel valet: https://github.com/laravel/valet/pull/55/files For anyone wanting to have a quick local dev environment (on a mac) you should certainly take a look. https://laravel.com/docs/master/valet
  13. 1 point
    Hello, I recently posted in this topic, but I decided to start my own thread because while I believe my issue is related to the one in that thread, they are not exactly the same: I have created a custom User Template in the method outlined in the docs. I am creating a directory, so it made sense that every page in the directory was a Directory Member, so they could log in and edit their own information while also keeping the entire directory protected behind a login wall. So the new user type is created: "directory-member". I then created two new roles: "member" and "directory-admin": The "member" only has the ability to View directory-member pages, and "profile-edit", which allows them to manage their own information. The "directory-admin" has the ability to edit any directory-member pages, and administer users. Some Directory Members are both, but all have at least the "member" role. The first hint that something was wrong was when I was testing a "member" user and I could not add a new item to a repeater on that profile. The url for the profile edit (this will be important shortly) is site.dev/admin/profile. The repeater is set up to load new items through AJAX. If this option is turned off, the rest of this issue is no longer completely valid. But as I have found what I believe to be a pretty large issue in the Processwire codebase, I thought it worth bringing up. See, every page (even a user) has a $page->editUrl() method, and it returns a URL like this: site.dev/admin/access/users/edit/?id=2096. That's all good and fine for users that have page-edit permissions, but if they don't, that link will resolve to the admin's equivalent of a 404. So the way that Processwire currently gets around this is by creating a specific editing area for a user to interact with only their profile: /admin/profile. And that works pretty nicely, except for the fact that nowhere is editUrl() ever made aware of the difference. editUrl() is not hookable, and whether or not a page is editable is based on the PagePermissions module. On top of that, there are several core modules that hardcode a search-and-replace (see InputfieldRepeater.module:627) where the editing screen is for Users. This doesn't allow for a huge degree of flexibility that is offered in other places throughout Processwire. If line 627 of InputfieldRepeater is changed from this: $editorUrl = str_replace('/access/users/edit/', '/page/edit/', $editorUrl); to this: $editorUrl = str_replace('/access/users/edit/', '/profile/', $editorUrl); ...the AJAX repeaters work. It's maddening! As is brought up in the thread I attached above, a lot of the features of page editing are missing within /admin/profile/, and it just makes for an altogether strange editing experience. A user who has "page-edit" permissions for templates other than directory-member, but does have "profile-edit" permissions, will see their user in the Page List, but cannot edit their Page unless they hover over the wrench and click the "Profile" link. It just seems - off. I think what this hinges on for me is that the editUrl() of the user should be "/admin/profile/" if that user is logged in (and their page should be editable from the Page List), or the "/admin/access/users/edit/" url; regardless of the URL, both links should resolve to the Page Edit screen, as the Profile Edit screen seems to be a unnecessarily neutered version of Page Edit.
  14. 1 point
    Welcome to the forums @redpanda Community member @dadish kindly released a PW3-compatible version of the Skyscrapers profile here: https://github.com/dadish/pw-skyscrapers-profile
  15. 1 point
    Another approach besides the one @flydev mentioned: $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); if($page->template != 'newsletters') return; // Only for specific template $page->newsletters->sort('-year'); // Sort the repeater how you want // Sequentially set the sort property of the repeater items $i = 0; foreach($page->newsletters as $item) { $item->sort = $i; $i++; } });
  16. 1 point
    If that's the exact code, you have an error. It should read "$p->parent->lastcreated", not "$parent->lastcreated". Perhaps that's the whole cause. I'd put the code in a "saved" (or even better "added", since the created property isn't changed after the first save) hook though, so that updating the parent only happens after successfully saving the book page. <?php $pages->addHookAfter('added', function($event) { $p = $event->arguments(0); if($p->template->name == 'book') { $parent = $p->parent; $lastcreated = $parent->lastcreated; if($p->created > $lastcreated) { $parent->lastcreated = $p->created; } // Save just the lastcreated field and leave modified user and time alone $parent->save("lastcreated", ["quiet" => true]); } });
  17. 1 point
    I have used this Contact Form in my website and its working fine. http://insignnia.in/
  18. 1 point
    Issue report here: https://github.com/processwire/processwire-issues/issues/553
  19. 1 point
    I don't know if I understood it right, but what about using FieldtypeRuntimeMarkup to show the image based on the option field selection?
  20. 1 point
    Okay, thanks @kongondo, you put me on the right track. The zip file can be extracted on Windows and Unix, but the "extension feature" doesn't work. Will find a workaround. Thanks again
  21. 1 point
    Did you see $options in $files? The exclude (array)?
  22. 1 point
    I haven't been following the zip conversation closely but don't ProcessWire's inbuilt functions not work? wireZipFile() has never failed me and more lately $files->zip(). I've just tried the following (example from the Docs) on my local Windows machine (EDIT: not a Windows Server though!) and remote linux machine and $files->zip() worked without errors (nested folders; PW 3.x): // Create zip of all files in directory $dir to file $zip $dir = $config->paths->cache . "my-files/"; $zip = $config->paths->cache . "my-file.zip"; $result = $files->zip($zip, $dir); echo "<h3>These files were added to the ZIP:</h3>"; foreach($result['files'] as $file) { echo "<li>" . $sanitizer->entities($file) . "</li>"; } if(count($result['errors'])) { echo "<h3>There were errors:</h3>"; foreach($result['errors'] as $error) { echo "<li>" . $sanitizer->entities($error) . "</li>"; } }
  23. 1 point
    @Zekathanks for pointing me there. I wasn't even aware that this issue exists. Otherwise I wouldn't have created my issue regarding tabs not being displayed correctly.
  24. 1 point
    I submitted an issue report: https://github.com/processwire/processwire-issues/issues/552 If you think, this should be fixed, please leave a comment on github. Thank you. I did not file this as a feature request because I consider it a bug. One would expect to display tabs as tabs and not as fieldsets. No matter whether in page edit or profile edit screen.
  25. 1 point
    Or if you prefer you could turn on the functions API: https://processwire.com/blog/posts/processwire-3.0.39-core-updates/#new-functions-api and do this: $homepage = pages('/'); PS Welcome to the forums!
  26. 1 point
    Hi @davenorton Welcome to ProcessWire! It is a scope problem: The $pages variable is not known inside your function by PHP. Use the global wire() function to get any API variable. At the beginning of your function, write this: $pages = wire('pages'); And it should start to work. Cheers
  27. 1 point
    @manuel1981 not sure if this would solve your problem, but i have a 3.x site that uses this module, and i do know that I changed line 389 https://github.com/Da-Fecto/TextformatterImageInterceptor/blob/master/TextformatterImageInterceptor.module#L389 from $class['align'] . " " to this: isset($class['align']) ? $class['align'] . " " : '', i'm not sure if that would be the cause of an error, but i was getting tracy log errors with this module before i changed it. Also, speaking of Tracy, you should have that installed so you can detect what if any errors this module may be generating in your setup...
  28. 1 point
    Hello All, I started with Joomla on this CMS parade. Then later I put my hands on Wordpress and eventually settled into Concrete 5. Recently I came to know about ProcessWire CMS, while I was looking for a better replacement for Concrete 5 in terms of robust, easiness, compact. I went through few Video tutorials of PW and read the documentation. The installation of PW was smoothy. The concept of Page is awsome. I like the relation of Page, Fields & Templates. There are many things I can equal to Concrete 5 from ProcessWire, yet PW offers a tiny minimal, code level approach for CMS. We have full control over design & data. There are some pitfalls I felt such no sitewide settings, global logo setup etc but it is easily tackled with some API codes. PW api seems amazing, it is par with what Concrete 5 Offers. I have done a simple website in ProcessWire now and going to do a lot further : http://insignnia.in/
  29. 1 point
    Dear @horst, thanks for the valuable feedback. Indeed you mentioned a very good point. I suspect I had a slightly different than usual understanding of how to remove image variations created by modules. The current implementation uses a glob (/{page folder}/{original file basename}.*) to delete variations. I'll update the module to use the standard naming scheme — this will have its benefits especially in edge cases, e.g. images will then still get removed if the module is uninstalled or deactivated. Also good idea about having a public method removeOptimizedVariations(). That will be very easy to implement with the previous issue.
  30. 1 point
    In my fork (linked above), the field is an images field (for the page specific SEO tab, not the default image).
  31. 1 point
    Welcome to Processwire! I inherited a club website built in Concrete 5, and it was so slow that page loads were taking over 20 seconds. The way the site had been structured wasn't particularly intuitive either. I'm not sure if it was a Concrete 5 issue or poor implementation, but after I converted it to Processwire, I had a dramatic improvement in page load times, and found the page editing was far more intuitive to the point I could hand over day-to-day editing to non-technical users, whereas the previous webmaster, even with several years using the system and some technical knowledge, still ended up making mistakes on Concrete 5. Processwire passed my '1/2 hour test', ie by looking at the documentation for no more than 1/2 an hour, I was able to have enough of an understanding of the system to start customising sites. As a developer, a 2 minute install is nice, but if it then takes hours to understand the structure of the system to start customisation, then it's not great.
  32. 1 point
    Hi @kaba86 as @dragan mentioned you can simply add another foreach loop to check another level down. I would defiantly check out some tutorials on using processwire to get yourself kickstarted in the right direction and theres lots of quality tutorials not to mention some of my own. https://processwire.com/docs/tutorials/ <?php $children = $pages->get('/')->children; foreach($children as $child){ $class = ""; if($page->id == $child->id){ $class = " current"; } if($child->id == $page->parent->id){ $class = " parent"; } // echo nav links echo '<a name="'.$child->title.'" class="ajax-link'.$class.'" href="'. $child->url .'">'. $child->title . '</a>'; // new code below $childChildren = $child->children; foreach($childChildren as $subChild){ $class = ""; if($page->id == $subChild->id){ $class = " current"; } if($child->id == $page->parent->id){ $class = " parent"; } echo "<div class='sub-item'>"; echo '<a name="'.$subChild->title.'" class="ajax-link'.$class.'" href="'. $subChild->url .'">'. $subChild->title . '</a>'; echo "</div>"; } } ?> The above is not optimised or elegent - just off the top of my head. I seem to remember one of the default themes has a funciton in it's _func.php file that gives you a nest page list given a page varible (and optional max depth) so you could use that too. Hope that helps (also please post you website when its done
  33. 1 point
    Thanks for this blog post @ryan. The new features are coming at such a pace I sometimes only have time to get excited, but not to try them out. Those recommendations are really useful (at least to me). I would enjoy to read more about use cases for the newly added stuff.
  34. 1 point
    I've opened a GitHub request: https://github.com/processwire/processwire-requests/issues/172
  35. 1 point
    Sounds to me like it should - I don't think module authors should have to worry about this. Are you interested in raising this with Ryan?
  36. 1 point
    Yeah, it is a concern for all external links in the admin, as the referrer will leak the login URL. It's straightforward to fix with a hook... $wire->addHookAfter('AdminTheme::getExtraMarkup', function(HookEvent $event) { $parts = $event->return; $parts['head'] .= '<meta name="referrer" content="no-referrer">'; $event->return = $parts; }); ...but perhaps this should be in the core admin themes.
  37. 1 point
    Thank you for pointing this out! Sorry for not checking and making an incorrect assumption. What about module authors who use Markdown links on the config settings page of their module, or in the ReadMe or Documentation (and you have @netcarver's ModuleReleaseNotes installed). I can't seem to find any issue on adding noreferrer etc to Markdown links. Any thoughts on what we should do on this front, if anything?
  38. 1 point
    I thought Google Analytics would log the origin of the event, but I tested it and it seems that it doesn't (unless that information is explicitly passed in the event, and I trust you won't start doing that). So that makes me feel a little better. This isn't true in the instances you mentioned, because Ryan has thoughtfully used the "noreferrer" keyword for the links, presumably because of the privacy concerns we're talking about here. And as a site developer you have control over referrers using the meta referrer tag if need be (in the past I have added this to the admin theme on some sensitive sites). By ecosystem I mean all the software associated with ProcessWire that isn't in the core. Rightly or wrongly, people's perception of a system is influenced by the third-party software associated with it. The WordPress plugin ecosystem is like the wild west, and that's a big part of the reason for WP's poor reputation as a platform for serious development. The PW module ecosystem is as good as we make it. You're absolutely right that the onus is on the user to check what they are installing to their site. But it has been quite nice so far to have a sense of trust that the folks who are contributing modules to the PW community are taking care of privacy and security in the ways that I think everyone expects. I completely get why developers are curious about how many installs, who is using their tools how often, and lots of other things I wouldn't mind knowing myself. I just don't think that curiosity in any way trumps the right of users to control what is being disclosed. Crossing this line to actively sending data to a third party makes me uneasy, and personally I won't be installing any modules that do this.
  39. 1 point
    I know this is an old topic, but I am currently running into some majorly-headache-inducing issues concerning the User Profile Page and the Page Edit screen - I can't sort out why they have to be different. I am about to post a new thread about my specific experience in this realm, but if anyone knows anything about this issue, I'd appreciate the help! Here's the thread I just created--
  40. 1 point
    I have been working with docker the last few days and in the end created a simple but flexible docker setup for local development. You can find the repository here https://gitlab.com/webhoes/pw-docker.git This is based on the work of undernewmanagement. The difference is that in that repository you had to put your files in /src. Side effect is that all projects in PHPstorm are now referenced as src... So I changed it so that you can put your files in the root. Therefor the directory of your project is referenced in PHPstorm. I also changed the docker-compose file and added a default config-dev.php. As long as there is a config-dev.php is will be used instead of config.php. This means you don't need to change you config.php on a local setup. Now it wil use config-dev.php. Ofcourse never upload config-dev.php to production. Add it to your .gitignore. There are 2 flavors of using this repository: 1 with a new install 2 with an existing site 1 With a new install git clone https://gitlab.com/webhoes/pw-docker.git <new project folder> git remote remove origin git remote add origin <your own git repository> Make sure that Docker/db/ is empty. copy the proceswire files in the root. remove folder and file /site/config-dev.phpp from a terminal make sure you are in your project folder and type docker-compose up. Go through the installer. The database settings are in the docker-compose file. Note: database location is mysql (not localhost) You now have a working local processwire on localhost 2 use a working copy from development For this setup you need the database backup module by @ryan (ProcessDatabaseBackups). Make sure you only have one file in the default backups/database directory. git clone https://gitlab.com/webhoes/pw-docker.git <new project folder> git remote remove origin git remote add origin <your own git repository> Make sure that Docker/db/ is empty. copy the proceswire files of your existing site in the root. The config-dev.php will take care of the connection to your database. the database will be filled with the sql file (see steps) disclaimer: I am not an expert of docker and stuff or processwire - just figured this out the last few days to make (my) life easier. If you find any mistakes or security issues, let me know.
  41. 1 point
    You need to enable 'modal' in module JqueryUI Don't set the href attribute. In this case the button will be wrapped by an anchor tag and you will be redirected to the url which you want to open in the modal. Use 'data-href' instead. If you set the property 'aclass' a class attribute value will be added to the anchor wrapper not to the button itself. Use function addClass() instead. Try this: wire('modules')->get('JqueryUI')->use('modal'); $btnAddNew = wire('modules')->get("InputfieldButton"); $btnAddNew->attr('data-href', wire('config')->urls->admin."page/add/?parent_id=1101&modal=1"); $btnAddNew->attr('id', "MyCustomAddPageButton"); // required for the additional button on top $btnAddNew->showInHeader(); $btnAddNew->addClass("pw-modal");
  42. 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/
  43. 1 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.
  44. 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...
  45. 1 point
    I am starting to use processwire and really liking it but having one issue which i wanted to ask help for. i am working on a directory type of site that consists of two types of information groups for now: Organizations (different types of organizations in different industries) People (different types of people who are in most cases affiliated with the organizations above) I want to create a relationship between the two types so i can list different people that are (or were) part of the organization and was initially able to do this simply by doing a page (lookup) field which i included in one of the above templates/pages to look up the other group. E.g. lookup people in the organization page. However this was too simple for my needs and i also wanted to be able to put related information (e.g. the person's title at the organization, when they started, when they left etc). So an intermediate type of place would be needed to store this which i was not sure how to do. So it would have to be a many-to-many relationship where more attributes about the relationship can be added. I also wanted an easy way to add more relationships (e.g. from the organization page, i want to be able to add more people that work or worked for the organization and also add more details like the title they have in the organization etc). Similarly also under a person's profile, i want to list the organizations he/she is (or was affiliated with). I know this is possible in PW, if someone could please point a novoice like me in the right direction on how to do this or please let me know if more information is needed. Thanks, Binit
  • Create New...