Leaderboard
Popular Content
Showing content with the highest reputation on 02/03/2016 in all areas
-
Finally, I got spared some time to work on a project I have been meaning to do for a while. This follows on from this request and other discussions about the pros/cons of an ApiGen for ProcessWire. I am all for such docs as long as two conditions are met: (i) That it is clearly indicated who the target audience is; and (ii) that the docs are regularly updated. I think this project meets both. I have created a GitHub project and project pages for hosting regularly auto-updated PHP ApiGen Docs for ProcessWire 3 (master and dev) as well as ProcessWire 2.8 (master). We also have ProcessWire 2.7 (master and dev) docs but these are not updated since this version of ProcessWire is no longer active. The whole doc-generation process is automated including auto-pushing changes to GitHub. The current cycle is: ProcessWire 2.8.x Master branch docs: updated once at the beginning of every month ProcessWire 3.x Master branch: updated once at the beginning of every month ProcessWire 3.x Dev branch: updated once weekly, every Friday Docs are generated for all .php and .module files under /wire/core/ and /wire/modules/. Currently, this is all done via my home PC. I am on a Windows machine so nothing could really go wrong... . Barring the unforeseen, these docs should be roughly in step with the latest ProcessWire commits. Now running on a remote server. Tools used Windows PowerShell (move over wget! ) wget Git-Bash Windows Task Scheduler (there's your cron right there ) cron Pear APIGEN Scripts: PowerShell, Bash Script, VBS and Batch files A couple of stress balls I hacked together a dark theme for this project, sublime-text default look. The CSS still needs some work, all help appreciated, thanks. If anyone would like to create an alternative theme, we could incorporate a theme switcher. Feeback, thoughts, suggestions (e.g. text in READMe, etc)? Credits to Ryan for writing such well-commented code...otherwise this project would not have been possible. From the READMe20 points
-
This module allows users to subscribe and unsubscribe to a newsletter, it doesn't handle newsletter creation and delivery (I use a foreign service for this). There is one method to subscribe (by using a form) and there are two methods to unsubscribe (by using a form or by providing a link in the newsletter). Furthermore you can notify any person e.g. an administator via email when an user has subscribed/unsubscribed. For detailed information have a look at Github.9 points
-
Just a few thoughts: I'd go with the legacy GeoIP databases and use geoip_country_code_by_addr (and optionally its IPv6 sibling). This should only be a few lines of code, plus, depending on the server you're running, perhaps a few more lines to download the current database every month (AFAIR, some Linux distributions even provide packages with cron jobs for that already included). Don't waste too much time trying to find the optimal solution by looking at browser headers etc. - those solutions don't exist. People surf through foreign proxies, use their en-gb browser on a trip to the U.S. or surf the U.S. page from an internet cafe in the UK. Make sure to avoid annoying the users. Embed the pointer to the native site in a prominent but pleasing way in the page, don't disturb them with javascript popups (modal or not). The first time, they'll click it away. The second time, they'll sigh and click it way. The third time... Whatever you do, never redirect a user automatically just because you think you know their origin or preferred language. They may well have a reason for wanting to access the URL they've entered or clicked. Instead, add a language switcher that lists all languagues/countries in their native language (the latter is not much of a point for U.S./UK/Ireland, but for the sake of completeness, I'll mention it here).4 points
-
------------------------------------------------------------------------------ This is officially released now with some fixes and a second storage handler based on SQLite3. ------------------------------------------------------------------------------ WireQueue WireQueue is a module that allows easy creation and usage of Queues in ProcessWire. It is based upon a basic (parent) module that can or should have one or multiple StorageHandler modules. This alpha pre release contains a basic plain text storage module, WireQueueTextfile. The base module creates the needed: FIELDS (wire_queue_type, wire_queue_state, wire_queue_storage_options) TEMPLATES (wire-queue-container, wire-queue-storage, wire-queue-tools) PAGES (wire-queues = container for all Queuepages, wire-queue-storages = container for StoragetypePages) ROLE (wire-queue-admin) Each storage module creates one page under wire-queue-storages. New Queues can be created in the backend by adding a new page under "Wire Queues". After creation one have to select a Storage type from availables list and publish the page. After that, there are some buttons available to start / pause / and close the queue. Putting and getting data to and from the queue is done via API calls. First you have to get the page that holds the queue object. // get and validate the queue handle if($queue = $pages->get(SELECTOR_TO_DESIRED_PAGE)->WireQueue()) { // wrap your data into an array and pass it into the queue $success = $queue->addItem($data); ... } // get and validate the queue handle if($queue = $pages->get(SELECTOR_TO_DESIRED_PAGE)->WireQueue()) { $data = $queue->getItem(); ... } Thats basically all what you want from a queue. Following are a few conveniences: $queue->getPage()->title gives you the title of the queue, ($queue->getPage() returns the page object) $queue->className() shows the StorageType of the queue $queue->getState() and $queue->getStateStr() returns the current state of a queue: 1 = new / empty 2 = enabled / running 3 = paused 4 = closed / archived $queue->itemCount() gives the total number of all pending items in the queue Here is code that gives an overview of all Queues in the system: $container = $pages->get('template=wire-queue-container'); $bodyContent = "<h1>$container->title</h1>"; $bodyContent .= "<p>There are currently {$container->numChildren} Queues defined:</p>"; $bodyContent .= "<ul>"; foreach($container->children() as $p) { if(! ($queue = $p->wireQueue())) continue; $bodyContent .= "<li>{$queue->getPage()->title}<ul>"; if(!$queue->ready2use()) { $bodyContent .= "<li>{$queue->className}</li>"; $bodyContent .= "<li>This Storagetype is not ready to use! The System seems not to provide all requirements.</li>"; $bodyContent .= "</ul></li>"; continue; } $bodyContent .= "<li>{$queue->className}</li>"; $bodyContent .= "<li>{$queue->getStateStr()} ({$queue->getState()})</li>"; $bodyContent .= "<li>Currently are {$queue->itemCount()} items pending!</li>"; $bodyContent .= "</ul></li>"; } $bodyContent .= "</ul>"; Following are a screenshots of the backend The module is on Github: https://github.com/horst-n/WireQueue Would be nice if someone has time and can test it a bit and report back.3 points
-
It doesn't. Whether a template file matching the name of the template (or the alternative name in the template config) is in fact present in the file system isn't stored in the database. You could assemble a list of all templates without file and put that into a selector though: $missing = array(); foreach($templates->find("flags!={template::flagSystem}") as $tpl) { if(! $tpl->filenameExists()) $missing[] = $tpl->name; } // Now you can get all pages with missing template file: $pages->find("template=" . implode("|", $missing)); // Or just children $page->children("template=" . implode("|", $missing));3 points
-
I like where you are headed with this Tom. One of the things that I find still quite cumbersome in PW is the need to return to the Page Tree after editing a page so I can find and edit the next page. Having the tree in the side menu would be a huge timesaver in my opinion, and also just help the user to visualize the site structure when they are editing a page - they can see where the page fits - context can often be very helpful in a complex site. I have actually been thinking about this today too and my thoughts are that the Setup, Modules, Access items should be along the top (like the default theme). Then the page tree could simply be in that side menu - no need for a second side menu. As far as implementing this, I don't think we need to have ajax loading of pages when clicking the edit butt on a page - it can simply reload the entire page with the page tree open to the page that is being edited. I also like the color scheme - matching the recent PW dev mockups.2 points
-
I've decided to make a start on the design, I thought I'd get a feel on what people think about the idea behind me doing this before continuing. I've always been passionate about UI/UX, and I'm always up for the extra practice wherever I can get it. Here is the design I've started: (http://i.imgur.com/2SY50ua.jpg - full size) So here are few things I've tried to solve with this: Unify the user journey, this page tree is going to be the main focus for every user and often unless you are an admin, the sidebar doesn't get used often. This is great from a UX point of view because that means they know exactly where everything is and there is no complicated bloat. I've tried to move very useful features into this screen as this is where I find users spend the most time. Also giving admins the ability to better define that user journey. The cog will edit the filter and the add filter button will, well, add a filter. Filters will work much like Peter mentioned ListerPro, however they will work just as well with Lister. I will do a mock-up if people want on how a filter page will look. The other people is moving items in the page tree. Many people expect to be able to drag and drop and if they want to move into a child and didn't open the page tree first. Then they will have to stop the move, open the tree and then move again. This works by hovering over a parent, the child will then expand. You can start a move just by dragging the page name. Another people I've seen people do, is not knowing to click on the edit on the right of the page name. Instead they frantically click the page tree and watch the page name highlight change, but nothing happen. I hope to do some work on this, but part of the problem is that the page names look like links. However I think they should be clickable to go into edit. I see people doing it, so they must feel natural doing it that way. I haven't yet thought of a solution for this as I also like how the click expends children. However one thing I've thought of is have it click it edit if it doesn't have children. If it does the will have to use the edit as normal. I'm not completely sold on this idea as I don't like the idea behind having two ways to get to edit. I can see this confusing users. Advanced Search will be the same as Lister.2 points
-
It works just fine ...but not always as, .....erm, clearly stated here2 points
-
Nice line about potential future changes. Added it to the readme The whites make my eyes ache . I'll look into setting up a theme switcher.2 points
-
Thanks for setting this up. While it's important to note that methods and such found via this are not necessarily intended as public API, and may be subject to change in later versions, I think it provides a good middle ground between pure code and manually edited docs Since you wanted feedback, one point I'd like to mention is the theme. This is partly opinion-based thing, but I find the light color scheme of the earlier apigen thing more readable. In the dark theme especially the dark lines tend to disappear, and some of the colors (such as the red headers) kind of make my eyes ache.2 points
-
From my point of view it doesn't matter that much, as long as the work is good and it is released for the general public under a proper open source license. We already have examples of someone else taking over a module that another person started, etc. To perhaps answer your question better, I tend to see the crowdfunding part mainly as an addition to current workflow where interested parties build and release modules for completely free. In this case you get paid for that initial work. If the module needs maintaining in the "fix bugs and make sure it works with new versions" kind of way, these should imho be provided for free as much as possible (or by accepting contributions from other interested parties). If the original developer can't handle this and the module has valid use cases, I'm sure we can find someone else who does have the time to do it. In the case of "nice module, but I think it needs big feature x", there's always the option of arranging another round of crowdfunding It's one option and I'm definitely interested, but like I said, I don't have much time on my hands right now; you might find it faster and easier to catch another developer for this2 points
-
I absolutely love the Reno Theme, however this is an aesthetic change. After using Craft Pro 2.5 for a recent project. I can see how the UI/UX for ProcessWire can be greatly improved. There are many things that I love about both CMS, but for me it's Crafts backend admin, ProcessWire for everything else. So the thing I like about Craft is: Almost like lister, there is a way to select an entry type and have that display custom columns and be filterable by table heading (eg. Title). It would be awesome if this was possible with ProcessWire, lister is great, however I find that it's quite advanced for average clients. If the bookmarks we create showed as filters? It could be quite nice. (I can do some mockups this weekend on UI/UX and illustrate my ideas). Don't get me wrong, I'm not saying that the backend admin isn't great. If it wasn't for my recent intense usage of Craft I wouldn't have noticed. I just feel like some attention to the UX/UI might improve the product. Mostly the consistency. Craft is incredibly consistent in its UI and that gives it just that little more polish.2 points
-
PrevNextTabs Module Github: https://github.com/outflux3/PrevNextTabs Processwire helper modules for adding page navigation within the editor. Overview This is a very simple module that adds Previous and Next links inline with the tabs on the page editor. Hovering over the tab shows the title of the previous or next page (using the admin's built in jqueryUI tooltips.) Usage This module is typically used during development where you or your editors need to traverse through pages for the purpose of proofing, flagging and/or commenting. Rather than returning to the page tree or lister, they can navigate with these links. Warnings If you are using PW version 2.6.1 or later, the system will prevent you from leaving the page if you have unsaved edits. For earlier versions, to avoid accidentally losing changes made to a page that might occur if a user accidentally clicks on one of these, make sure to have the Form Save Reminder module installed. http://modules.processwire.com/modules/prev-next-tabs/1 point
-
This is already available within the RTE, I think the same functionality should be brought through to the Image field (note: I am not asking for a media manager )1 point
-
some recently launched pw-powered sites... Roger Shapiro Fund for New Music Custom blog & news, projects listing and works w/ dataTables... using Soma's social share for the sharing buttons http://www.rogershapirofund.org/ Daniel Lippel, Guitarist http://danlippel.com/ Flowers by Selina Website for floral designer in Westchester, NY. Features custom blog, homepage featured portfolio and full masonry portfolio. http://www.flowersbyselina.com/ Eric Huebner, Pianist media handled by Soundmanager2. A frontpage ajax-powered widget was implemented to let visitors browse the concert & event calendar, with a browsable month view. http://www.erichuebner.com/ Anderson Chase Gallery Simple one-pager http://andersonchasegallery.com/1 point
-
Very nice! - ähm but unfortunately not my colors. Ough. Please can we have a less colorful theme or a theme switcher with one less colorful, once all other is running? please, please, please, ...1 point
-
edit u. index.php file + add 2 top on.line afters namespace $_SERVER['REQUEST_URI']=str_replace('index.php','',$_SERVER['REQUEST_URI']); when.u no needs index.html no more rember to deletex that ok1 point
-
@kongondo Finally got an opportunity to look at this Module(s). Deeply impressed and grateful to you (Ryan et al), this is fabulous, looking forward to building this in1 point
-
1 point
-
Would love to see them. Multi-column listings were one of things I most missed about MODX after a brief fling with Expression Engine and it's Channels concept. I've used Craft a few times and agree, the UI is very tight.1 point
-
Hi Peter, yes ListerPro is very much what I was referring too, thank you for that. However, I'm still keen to look at the UI/UX. If anything just to better demonstrate my ideas.1 point
-
@adrian Yes and no. Basically this module simply displays the correct language. What I need is to check if they are from the UK and then redirect the user to the .co.uk version of the website. Or Trigger a pop up that asks them if they would like to visit the UK version of the website.1 point
-
1 point
-
Thanks Testing with the plain text storage is ok in that context. But to use it for production, I would suggest you wait for the SQlite storage, because with it you will be able to store different states of an email sending job: new/added to the queue pulled by a worker for execution successfully sent by a worker, or not successfully sent At least it should store sent (yes / no) and track (max) tries.1 point
-
This module is amazing...I'm gonna test very soon for sending emails after user actions.1 point
-
1 point
-
A "Like" isn't enough Great work and a big step to an (automated) up to date PW documentation! A light color schema would be better. As teppo said.1 point
-
Managed to get round to this; fully auto-generated and regularly updated ApiGen docs for all currently maintained ProcessWire branches...More info here1 point
-
Very nice, just what the doctor ordered! Seem to work fine on 3.0.6. Perhaps the UI could be polished more but otherwise it's a huge time saver.1 point
-
Without (hopefully) derailing this discussion too much, that's a good start: the server needs to be configured properly. Misconfigurations open it up for vulnerabilities. The most important thing in this context, though, is escaping commands and arguments properly, preferably using a whitelist approach. None of this applies to exec only, of course – code execution features just tend to increase the risks involved. One thing that's kind of unique to code execution features is the amplification effect they have: if an attacker gains access to an application that doesn't allow her access to code, the most she can do is mangle your data. If there's a configuration option somewhere that allows her to control the output sent to exec(), such as the command it will execute, she suddenly has access to a lot more than just that. Then again, the same thing goes for tools that allow you to edit your template files etc. online1 point
-
Just to qualify my question above, I'm just trying to think through the whole idea of 'crowd-funded' modules, since, IIRC, it is uncharted territory for us (although quite interesting). Just wondering if it is something we need to think through a bit more.?..or am just being too fussy. OK, back to my hiding place...1 point
-
That's interesting to read, because it's something I've been thinking quite a bit lately. As I'm working on complex ideas that need templates, fields and pages in their correct places, I'm more and more starting to use individual PW instances to keep things from getting cluttered up, but one day they'll need to be brought together on one system. I definitely won't want to recreate everything by hand, so some kind of export-import functionality will be essential. A lot of that can apparently be done with adrian's ProcessMigrator. I'll have to see how far this gets me, especially with multi-language installations and complex custom field types involved. I'd definitely prefer to build upon an existing module that re-invent the wheel from scratch. If I had to, though, I'd use PHP and PW bootstrapping. No sense introducing foreign tools or languages that may interpret data differently.1 point
-
Just wanted to say that this sounds very interesting. Been meaning to build a module like this, though was thinking of limiting it to PNGs since that seems to be the only case where optimization doesn't necessarily mean sacrificing quality. I'm also aware of the minimize.pw service, but a) it's not free (as in beer or as in freedom), b) it doesn't seem to be well maintained and c) I don't want to rely on external services unless I really trust them (especially when it means sending client data over to an external server). As a reply to Horst, kind of, I'd like to point out that whether or not the host allows exec(), if there's a similar solution that doesn't require it, that's in my opinion always the better route. Even when you're taking every step to make sure that it's safe, exec() is still potentially dangerous. Any and all mistakes have the potential to compromise your entire server (or, at the very least, your personal account). There's a reason why exec() and other code execution methods tend to trigger warnings from security scanners. That being said, I won't deny that executing external apps via PHP can solve some situations where nothing else helps. I've had to use it many times over myself. Edit: just took a closer look at Tinify. Somehow I managed to miss earlier the point that it is also an API, i.e. requires sending the data to their servers for processing. Can't say that I would be exactly happy with that, but will give this a while; perhaps it's a compromise worth making. In the meantime I'll be looking into some alternative approaches.1 point
-
If you're only talking about the navigation then just edit Admin > Pages and unhide the page.1 point
-
This week we've released ProcessWire version 3.0.5 which actually contains quite a lot of changes. Now you can nest repeater fields (repeaters in repeaters) and use dynamic/AJAX loading for all items. Plus we've got the first test version of Repeater Matrix released, and new support for field templates… https://processwire.com/blog/posts/more-repeaters-repeater-matrix-and-new-field-rendering/1 point
-
Just bumping this thread - I have updated the title and first post to now refer to PW 3.0. It would be great to start seeing the modules directory full of modules tagged as compatible with 3.0 before it is declared stable and released. Hopefully 3.x will attract a new round of developers looking to see what PW is all about - we don't want it to look like our modules aren't being updated. Even though we all know that in most cases older modules still work in newer versions of PW - this is often not the case with other CMS's.1 point
-
I have to say that the form API works pretty well in the frontend. I have several sites where I use it without issues. Once you get the hang of it, it is actually quite nice to interact with. Only thing I am missing is a more easy way than the current to get more control over the rendered markup. Formbuilder comes to the rescue here. If I remember correctly, when UI framework support was introduced to formbuilder, Ryan stated that the core functionality was altered to easier support UI frameworks. But I never found any hints on how to easily alter rendering of form markup (especially field wrapper's markup and attributes) other than through hooks. Nevertheless, I agree that it would be nice to have a docs section dedicated to this topic. Or at least have a link collection to relevant forum posts that deal with frontend forms, processing and saving of input values. Links I can come up with quickly: https://processwire.com/talk/topic/2089-create-simple-forms-using-api/ and, of course, Soma's great gists (big kudos) https://gist.github.com/somatonic/5011926 (build and process generic forms from page templates) https://gist.github.com/somatonic/4027908 (build and process forms manually with API) https://gist.github.com/somatonic/4150974 (upload images) https://gist.github.com/somatonic/5415646 (form with fields in table) https://gist.github.com/somatonic/5233338 (manual form markup with file upload handling)1 point
-
Example for a use case with importing things. This is a raw draft with a bit pseudo code: // you have created a queue in PW, the ID of the page is 2000 for example // here is some skeleton code for an importer that uses this queue // get and validate the queue handle if(! ($queue = $pages->get('id=2000')->wireQueue())) exit(); // we could not get the Queue page // now start to scan / read data for your imports, wrap each record into an array and put it into the queue foreach($pages->find(YOURSELECTOR) as $p) { $data = array($p->field1, $p->field2); $queue->addItem($data); } // now start to process your items by pulling one after the other from the Queue while($timer < $maxtime) { $data = $queue->getItem(); // process the $data ... } $session->redirect('./');1 point
-
Hey mr. Ivan! Nice to hear from you. There can be some different usecases. Normally you want to use a Queue for decoupling time intensive tasks from the websites responses so that the users doesn't have to wait long times. For example, if someone booked / collected something on a site, there will finally an email sent to him / her. If the script would wait until it could connect to the smtp server and has sent the email, it could be that the smtp server is busy and delays the sending. With a Queue, you simply drop in this job and give fast response to the users screen: "Thanks for your booking! We will response by email soon.". Another script will pickup the job and proceed it. So, decoupling time intensive tasks and optionally split up the work to multiple workers if usefull / necessary. Another example would be sending a newsletter to 5k recipients. It seems better to me to have those temporary data seperated from the main Database in regard of Backups / Restores. With WireQueue you can create and controll Queues visually in the backend. This wouldn't be necessary but I found it usefull and comfortable. Currently there is only a very simple StorageModule available with plaintext files. The next one uses SQlite Databasefiles what is much more comfortable as it opens the WireQueue to not only put and get jobs into it but also can be used to store the current state of each job. Or if the collected data should be exported to other systems for further processing, etc. You can use whatever storage type you like. You only needs to create your own storage module upon the abstract class that comes with the module. Currently there are only comments in the code itself and the WireQueueTextfile module for detecting how it should be done. But it isn't complicated. You can setup one that uses a MYSQL table in another DB than that from your PW installation. etc. etc. More and better information will come later in next step. Does that help?1 point
-
Hey, mr. horst! Looks like something I could make great usage of... But not sure that I understand the thing right. Could you please write a few words on what it is, what and how it is supposed to do. Maybe a use case... I understand It as a way to add multiple pages through the api without the risk of running out of execution time. Am I close?1 point
-
Update: So I've been using Pete's dashboard module instead of the technique described above; it's quicker to setup, and easier to clone to other installs, and no need to have code in various places like the themes folder and in ready.php The hope/plan is to turn it into a full widget enabled dashboard module that i can install on various installations a) without having to do any hardcoding b) enable control over which widgets are shown on the dashboard (by user/role/permission) c) allow for easy configuration of colors, icons, columns, etc. To achieve this I setup some templates for different widget types, one is a shortcuts widget, another is a page lister widget; these each have pages and fields to configure them; i can set them to appear by user/role. in the future i can add different types of widgets as needed and then include them in the needed user's dashboard. This is using a combination of a free (MIT licensed) admin theme for bootstrap, but instead of using bootstrap as the css layout, it uses a tiny grid called rwdgrid which i s 2KB; it uses the box, and other widget classes from the admin theme.1 point
-
http://modules.processwire.com/modules/process-hanna-code/ I am guessing your HC exists on the page with ID 1187? So it will always evaluate to true. Use wire('page') to refer to pages originating the request.1 point
-
[news from the trenches] I created a page called "Question Bank" and populated it with 3 questions. I'm showing one per page and storing the answers in the session, along with the user id. I'm using the session values to mark the choice made (if the user goes back to a previous question) and I'll save it in the DB on the end of each quiz attempt. The code is on github (along with a db dump) -> https://github.com/sjardim/ProcessWire-Quiz-App This is the admin so far.1 point
-
Don't call it pages, call it content type. While ProcessWire is using the name or label "Pages", it can be basically everything. A user is a page, the whole admin area consist just of pages and you could create your own content types. What you mentioned is basically there. Use templates for your content types, link them with the Page (PageSelect) field and then you can cross-access values in the tempalte files. Quick Example: Create a template for product, add the needed fields. Create "Products" by creating new pages with that template. Now create a field with of the "Page" type and call it product. This allows you to link pages. Set it to "Single item" and add it to your desired "Page"-Template. Now you can select your product on the other "Page" and access it via API with $page->product->title1 point
-
Is anyone here a heavy bookmarker like I am? Typically I'll get most of my news from Hacker News and Slashdot, followed by some great blogs on a daily basis. I usually never have time to read an article in depth when I first come across it, so I'll bookmark it for later. Or, if I quickly need to get up to date on some topic, I'll do a search (usually by tags) and familiarize myself with important stuff I've bookmarked in the past. After having used browser native based bookmarking (Firefox and Chrome), then Delicious, then Diigo, then Pinboard and becoming frustrated by all of them for various reasons and limitations, I've decided to roll my own little single user (and non social) bookmarking system with ProcessWire (with Bootstrap 3 as the frontend framework). It's still a work in progress, but it takes the best of all those systems with my own power features. It also utilizes ajax for certain actions. I'll need to create a Chrome extension to tie it all together. I have to say however, after working non-stop on it for hours on end and not being able to think of anything else, it's looking slick. Damn you ProcessWire for making this so enjoyable. Jonathan1 point
-
Why not? The way I would solve this is to create pages for shared assets, probably with a one-one relationship between pages and images. Something like /shared/images/... Give each of the shared image pages a title and an image. Then use a page reference field, perhaps with an asmSelect (multiple selection) to select the header images you want shown on each of your pages. In situations where I have image selection like this, I also like to provide a default/random selection in cases where nothing is selected (or too few are selected). So I might do something like this: $limit = 3; // number of images required $imagePages = $page->header_image_pages; // page reference field $n = $limit - count($imagePages); // n=number of images we need to get if($n > 0) { // not enough images selected $imagePages->add($pages->find("parent=/shared/images/, sort=random, id!=$imagePages, limit=$n")); } else if($n < 0) { // too many images selected $imagePages = $imagePages->slice(0, $limit); } // output the images foreach($imagePage as $imagePage) { $image = $imagePage->image; echo "<img src='$image->url' alt='$imagePage->title' />"; }1 point
-
Just add something like this to the top of your events index page. You could compartmentalize this into a LazyCron call, but for such a simple thing it's really not necessary. $events = $pages->find('parent=/events/, date<"-3 months"'); foreach($events as $event) { $event->of(false); $event->addStatus(Page::statusUnpublished); $event->save(); } Btw, when testing something out like this, always comment out the $event->save(); the first time and take a look at what pages get affected by echoing them rather than saving them, the first time around. i.e. // $event->save(); echo "<p>Unpublishing: $event->url</p>"; Once confirmed that it is behaving the way you want, then remove the echo and uncomment your save();1 point
-
Here's a function that would return all the children in a month. Replace the last param ($field) with the name of the date field you want it to look at, otherwise it defaults to the 'modified' field, which probably isn't what you want (but was what I used to test the function). <?php /** * Return all of the page's children where $field falls in $month and $year. * * @param Page $page The page that has the children we are finding. * @param int $month Month you want to match. * @param int $year Year you want to match. * @param string Name of the date field to check. * @return PageArray All the matching children. * */ function childrenInMonth($page, $month, $year, $field = 'modified') { $startTime = strtotime("$month/1/$year"); $endTime = strtotime("next month", $startTime); return $page->children("$field>=$startTime, $field<$endTime, sort=$field"); } Below is an example of how you might use this function in your template. This code shows examples for both URL segments and GET vars. If you wanted to use URL segments, you would need to go in to the Admin CP, click on Setup > Templates > Your Template > Advanced > URL Segments > Set it to an asterisk "*". That tells it to allow any URL segments to pages using that template. And here is code that first checks for a URL segment, then GET vars, and defaults to current month/year if none is provided. <?php if($input->urlSegment1 && preg_match('/^(\d{4})-(\d{1,2})$/', $input->urlSegment1, $matches)) { // A URL segment matched in the format of year-month, i.e. /news/2010-12 $month = $matches[2]; $year = $matches[1]; } else if($input->get->month && $input->get->year) { // GET vars were provided with the year and month $month = (int) $input->get->month; $year = (int) $input->get->year; } else { // No year/month provided, so display items from current month $month = date('m'); $year = date('Y'); } // display a headline with selected month/year echo "<h2>" . date('F Y', strtotime("$year-$month")) . "</h2>"; // find the matching pages $children = childrenInMonth($page, $month, $year); // output a list of the matching pages echo "<ul>"; foreach($children as $child) { echo "<li><a href='{$child->url}'>{$child->title}</a></li>"; } echo "</ul>";1 point
-
@hani, not sure about your query. But it is possible to write a SQL query that does compare two fields on pages. I'm no SQL guru either but I've done this in the past but didn't post. Here a example with two joins comparing two date fields on page: $query = "SELECT id FROM pages p LEFT JOIN field_mydate m1 ON p.id = m1.pages_id LEFT JOIN field_mydate2 m2 ON p.id = m2.pages_id WHERE m1.data > m2.data AND p.status < 2048"; $res = $db->query($query); $ids = array(); while($r = $res->fetch_array()) $ids[] = $r['id']; // fetch the ids $pa = $pages->getById($ids); // get pages foreach($pa as $p){ echo "<p>$p->title - $p->mydate - $p->mydate2</p>"; }1 point
-
Joss actually emailed me a similar question and I'll duplicate my reply here since it seems relevant: Performance as it relates to database is really not an issue that one needs to consider much (or at all) when it comes to creating their fields. Most field data in ProcessWire is loaded on-demand. It loads data selectively and only when it needs it. This enables it to be highly memory efficient with large quantities of pages in memory at once. When you have a $page, behind the scenes, none of the page data is actually loaded until you access it. For instance, if you access $page->body, then it goes and retrieves it at that moment (if it hasn't already retrieved it before). MySQL is extremely fast with simple primary key, non-joined selects, and we take advantage of that. What I'm trying to get across is that quantity of fields does not translate to an increase in joins or other factors that would slow the system down. Where ProcessWire does join data automatically is at page load time is when you check the "autojoin" box on a Field's "advanced" tab. Some fields you know will always be needed with every $page instance, and that's what autojoin is for. Typically, I make my "title" field autojoin, as it is already by default. I've hidden that autojoin option under the Advanced tab simply because most people never need to consider it. The original intentions behind autojoin have become less applicable than I originally thought [with regards to performance], so it's not something that comes up that often. ProcessWire also uses joins when it performs queries for $pages->find("selector"), and related DB-querying selector functions. It joins all the tables for fields that you query. So if you perform a find for "date>2012-12-19, body*=holidays" then it's going to join the field_date and field_body tables when a value matches. Though it doesn't do this for the purpose of loading the data, only for matching the data. Technically this type of query could be potentially faster if all those fields were in one table. But that doesn't translate to results that matter for us, and doesn't affect the way that you should use ProcessWire. The benefits of our one-table-per-field architecture far outweigh any drawbacks. I put a lot of time into finding the right architecture and balance here when coding ProcessWire 2. Incidentally, ProcessWire 1 did use the one-table approach (all the field data was stored with the page rather than in separate tables) and it was far less efficient with memory, and about the same in terms of performance. It's better to re-use something like "body" (when possible) rather than create "article_maintext" or other template-coupled variations like that. The reasons for that are for your own benefit. It is less to keep track of, and tends to foster better consistency. It also results in more reusable code and broadens the potential of where the data can be used. Take the example of an on-site search engine, like you see in the upper right corner of processwire.com. If we know that the main text field(s) of most templates has some consistency in their field names (like title and body), then we can write code that doesn't need to know whether something is an article, a press release or a product. We can find all pages that match "holidays" in the text just by doing this: $pages->find("title|body*=holidays"); But if created a separate textarea field for every template, then any code that queries those fields needs to know a lot more about them: $pages->find("title|article_maintext|pr_maintext|product_maintext*=holidays"); While that still works, it doesn't scale nearly as well. This also translates to the code you use to output the results. If you want to show a snippet of the matching text with the search results, you are going to have a lot more fields to consider than just "body". Now if each of your templates genuinely needs very different settings for each of their main text fields, then of course it's fine to create them as you need them. But in the real world, I think you draw more benefit by planning for reusability when possible. The benefits are for you (the developer), as it doesn't matter much to ProcessWire. Reuse fields where it's obvious that the name of the field makes sense in the context of multiple templates. If template "employee" needs a date_of_birth field and template "press_release" needs a date_publish field then just create one field called date and use it on both templates. On the other hand, if you need multiple date fields on the same template (like date_unpublish) then more specific field names start to make sense. In that case, I would usually use my date field for publish date, and create a separate date_unpublish field for my unpublished date field. Though some may prefer to actually have separate date_publish and date_unpublish fields because they are obviously related by name. Ultimately, use what works best for you, but always keep an eye out for obvious reusability potential with fields. I think that most people naturally arrive at the right balance for their needs after some experimentation. What is a best practice for one need might not necessarily be for another. So these are mostly general purpose guidelines and people should find what makes the most sense in their context. For the majority of cases, I think avoiding tightly coupled template and field names is a better strategy. TL;DR: It doesn't matter to ProcessWire what you do. Aim to reuse fields when you can and when it makes sense, for your benefit.1 point