Leaderboard
Popular Content
Showing content with the highest reputation on 08/25/2013 in all areas
-
Greetings, What makes ProcessWire so excellent is the ability to do all kinds of work at the API level, so that you can essentially create a custom admin for your projects. Editing a page is of course a crucial part of any custom admin. NOTES: Of course, you must cutomize this to your project. Also, in my code I am editing the page directly inside the page itself. In other words, you display a page as usual, but inside it you have your edit code, as well as code to save the page after editing. The other option would be to link to another page just for editing. Editing does get rather involved. Below is a technique I've used. I'll break editing down to several steps, then later I'll put it all together as one. Here goes... Step 1: Isolate Who Has Editing Rights You don't want anyone who can view the page editing it! I use code like this to limit editing to people with either an "editor" or "superuser" role. We open it here, and close it later in Step 6: <?php if ($user->isSuperuser() OR $user->hasRole("editor")) { Step 2: Set the $page Variables (Except Title) to Hold Edited Values Take inputs received from a submitted form and use those values to replace current $page values. For this example, I am only using two fields to keep it simple. And they are text fields. We hold off on setting the title, since that needs special handling: <?php if ($input->post->title) { $page->set("first_name", $sanitizer->text($input->post->first_name)); $page->set("last_name", $sanitizer->text($input->post->last_name)); } Step 3: Edit Title Field, but Only if the Title is Unique, Then Save the Page You need something like this so you don't get an error if the title you apply to the edited page collides with the title of an existing page. The code below confirms that the title is unique and allows you to set the title, and only then save the page: $thistitle = $page->title; $matchedtitle = $input->post->title; $checktitles = $pages->find("parent=/[path]/[to]/[parent]/, title=$matchedtitle|$thistitle"); $titlecount = count($checktitles); if($titlecount < 2) { $page->of(false); $page->set("title", $sanitizer->text($input->post->title)); $page->set("name", $sanitizer->text($input->post->title)); $page->save(); Step 4: Refresh URL Think about it... If while editing this page we changed the title, the URL you are on is no longer valid. Here's a simple bit of Javascript to handle this. The code below also closes out the conditional set in Step 3: $refresh=$page->url; ?> <script type="text/javascript"> window.location = '<?php echo $refresh ?>'; </script> <?php } Step 5: Handle the Scenario When the Page Title Collides In Step 3, we edited the page title because it passed the "unique" test. But what if it fails that test? We would move to this section of code, where a message lets the user know there is a problem. A bit of Javascript helps make the warning fade in so it is more noticeable: else { ?> <div class="admin_error_box"> <p>Sorry, there is already a page using this title: <?php echo $input->post->title?>!</p> <p>Please enter a different title in the form.</p> </div> <script> $(function() { $('.admin_error_box').hide().fadeIn(3000); }); </script> <?php } Step 6: The Edit Form We need a form to capture the submission of edits. It would look the same as your page-creation form, but would have to be pre-populated with the current values of the page, which will also change upon submission of the form. The last bit of code closes out the check on user roles set in Step 1: <div class="page_create_form_box"> <p class="form_heading">EDIT THIS PAGE USING THE FORM BELOW</p> <form action="<?php echo $page->url ?>" method="post"> <ul> <li><label class="label_class" for="title">Page Title:</label> <input type="text" class="input_class" name="title" value="<?php echo $page->title ?>"></li> <li><label class="label_class" for="first_name">First Name:</label> <input type="text" class="input_class" name="first_name" value="<?php echo $page->first_name ?>"></li> <li><label class="label_class" for="last_name">Last Name:</label> <input type="text" class="input_class" name="last_name" value="<?php echo $page->last_name ?>"></li> </ul> <button class="admin_submit" type="submit" name="submit">SAVE EDITED PAGE</button> </form> <?php } ?> Step 7: Putting it all Together Now let's put all of this code into one continuous routine. <?php if ($user->isSuperuser() OR $user->hasRole("editor")) { ?> <?php if ($input->post->title) { $page->set("first_name", $sanitizer->text($input->post->first_name)); $page->set("last_name", $sanitizer->text($input->post->last_name)); } $thistitle = $page->title; $matchedtitle = $input->post->title; $checktitles = $pages->find("parent=/[path]/[to]/[parent]/, title=$matchedtitle|$thistitle"); $titlecount = count($checktitles); if($titlecount < 2) { $page->of(false); $page->set("title", $sanitizer->text($input->post->title)); $page->set("name", $sanitizer->text($input->post->title)); $page->save(); $refresh=$page->url; ?> <script type="text/javascript"> window.location = '<?php echo $refresh ?>'; </script> <?php } else { ?> <div class="admin_error_box"> <p>Sorry, there is already a page using this title: <?php echo $input->post->title?>!</p> <p>Please enter a different title in the form.</p> </div> <script> $(function() { $('.admin_error_box').hide().fadeIn(3000); }); </script> <?php } ?> <div class="page_create_form_box"> <p class="form_heading">EDIT THIS PAGE USING THE FORM BELOW</p> <form action="<?php echo $page->url ?>" method="post"> <ul> <li><label class="label_class" for="title">Page Title:</label> <input type="text" class="input_class" name="title" value="<?php echo $page->title ?>"></li> <li><label class="label_class" for="first_name">First Name:</label> <input type="text" class="input_class" name="first_name" value="<?php echo $page->first_name ?>"></li> <li><label class="label_class" for="last_name">Last Name:</label> <input type="text" class="input_class" name="last_name" value="<?php echo $page->last_name ?>"></li> </ul> <button class="admin_submit" type="submit" name="submit">SAVE EDITED PAGE</button> </form> <?php } ?> My apologies for any problems with the formatting of the code above (please use your editor to assure proper tabs). Notes: - If you include checkboxes or other field types in your page, the editing is a bit more involved. - If you have image fields, you would have separate actions connected with those. For more information on handling image fields in custom forms, take a look at this: http://processwire.com/talk/topic/3105-create-pages-with-file-upload-field-via-api/ That should get you started! Follow up if you have more questions! Thanks, Matthew5 points
-
It is possible, this is the code you would use to get all pages that link to the current page from that field: $pages->find("related_pages=$page") You can even create a page field where you can select pages from all pages that link to the page you are editing. For this, just add this as the "custom php code to find selectable pages" on the "input field settings": return $pages->find("pageField=$page"); // where pageField is the name of the selectable pages template You should still define the parent or template of the selectable pages either on the code or on the other options from the field. <- forget the last part. The code overrides the previous options5 points
-
4 points
-
This is intentional behavior. Personally I'd prefer to have this as a config setting somewhere, though, just to cover those (admittedly very rare) cases where huge pager makes sense.3 points
-
You can set up customs selectors or even PHP code for page fields. I don't think there's a selector for this case so you might want to add PHP code that collects all grand children and returns it in a new PageArray: $rtnPages = new PageArray(); foreach ($pages->get("/items/")->children as $categories) { $rtnPages->append($categories->children); } return $rtnPages; Or if your items in the categories have a certain template you can select by template: template=template-name3 points
-
As kongondo stated, PageFields are the way to go, they are very flexible. It looks like your subcategories are unique in each main category so you could build them in a page tree Categories - Disciplines - - Advertising - - Architecture - - ... - Locations - - Budapest - - Glasgow - - ... - Themes - - Animals - - Automotive - - ... If you want you subcats to be able to have multiple parents/maincats you might want to add the subcats via ASM select (an option for PageFields) in the maincat template rather than as child pages. As for how to be able to select the categories when using them here are some examples: http://processwire.com/talk/topic/4348-selectable-pages-mutual-relation/ and http://processwire.com/talk/topic/4344-autocomplete-input-for-page-select/2 points
-
By coincidence I'm working on a website that needs this feature (that's where the second tip from above came from). I also had the need to limit the selectable elements to those that were not selected yet by other pages. This is what I came up with: // this code goes on the "custom php" of the field settings // this field is included in the template "team", and the goal is to choose players for that team // players should be available (not selected yet by other teams) $players = $pages->find("template=player"); $teams = $pages->find("template=team, players.count!=0")->remove($page); // important to remove this page foreach($teams as $team) { foreach($team->players as $player) { $players->remove($player); // remove from our list the players that are in other teams } } return $players; edit: added "players.count!=0" to the teams selector. It's not my case, but if there are lots of teams this filter could make some difference.2 points
-
No it wont. Did you even read the docs I pointed to Andrei? Did you read Diogo's post above? $page->get(1006)->tv will not get you anything. First, $page always refers to the current page. Secondly, tv from what I can tell is a child page of home whose id is also 1006. I gave you code to insert first image of tv in home page in my example code. OK, one last time... Home (id = 1) TV (id = 1006) option 1: Get by page ID echo "<img src='". $pages->get(1006)->images->first()->url ."'>";//images here is the name of the multiple image field Option 2: Get by page name echo "<img src='". $pages->get("/tv/")->images->first()->url ."'>";//images here is the name of the multiple image field These are just examples...see Diogo's post how to get the link to the child page (tv)2 points
-
Interesting solution for creating and managing Gists on Chrome https://chrome.google.com/webstore/detail/gistbox-desktop/pdjgfbgklbmmigkmmdbbhfchdldngkml2 points
-
I'd consider that a bug. There are reasons to install language support even with only 1 language, like if you want to take advantage of static translation capability in template files. I've added this as an issue on GitHub, and I'm hoping to get through the current queue of issues here over the next few days.2 points
-
I needed a field that would allow me to select one or more templates, very much like the Page Select. So I created a module that does just that! I based it off of Ryan's FieldtypeModules because the functionality is quite similar. You can also define which templates are selectable by the asmselect field. Hope this helps someone that wants to do the same thing! FieldtypeTemplates.module1 point
-
I've been working on making repeatable fields for ProcessWire for a couple weeks and actually now have it nearly ready. I need to do some more testing before releasing it, but wanted to give you a little preview. (please view the full screen version for better quality) Accessing repeatable fields from the API is super-easy. They are fully searchable/selectable with the API just as easily as with any other fields. So if you wanted to find all pages that had a buildings field with a floors value of 50 or more, you'd do this, for example: $pages->find("buildings.floors>=50"); Lets say you are on the page with a 'buildings' field and you want to print out all the building names and number of floors. It works exactly the same as page references: foreach($page->buildings as $p) { echo "<p>{$p->building_name}</p> has {$p->floors} floors.</p>"; }1 point
-
Hi, I just uploaded the first version of the SchedulePages module to Github: https://github.com/f...r/SchedulePages This plugin module allows you to schedule (un)publication of pages. I hope you guys will like it. //Jasper Usage: ====== Place the SchedulePages.module file into the site/modules folder and install the plugin from the admin area. Install/activate the LazyCron module (if you haven't already). This module is part of the Processwire core, but it isn't activated by default. Add the following date fields to your template: publish_from publish_until Note: the fields are already created during the installation of the module That't all. LazyCron will run take care of (un)publishing your pages that have a the publish dates set. It will run on every hour. Please note: LazyCron hooks are only executed during pageviews that are delivered by ProcessWire. They are not executed when using ProcessWire's API from other scripts. Edit: Changed the name of the module and function as Ryan suggested below. Edit 2: Updated instructions. Required fields are now automatically created and from now it runs every hour. Edit 3: Added module dependency. The updated module is on Github1 point
-
Field dependencies are coming in ProcessWire 2.4, and I just wanted to give you guys a little preview of it. The development of this new feature is being sponsored by Avoine, the company where Antti works (he also specified how it should work). Field dependencies are basically just a way of saying that one field depends on another. It dictates which fields should be shown in a given context. In our case, it also gets into whether a field is required or not. This short video demonstrates how it works: (switch to the 720p and full screen version, as YouTube's default settings for this video make it impossible to see): // Edit @Adamkiss: Here's link for those on mobile: youtu.be/hqLs9YNYKMM The implementation here is done both client-side and server side. Javascript handles the showing/hiding of fields and the required vs. not required state changes. On the server side, it doesn't process any fields that aren't shown, and honors the required rules. A separate processing occurs both client side and server side, ensuring that the user can't make their own rules by manipulating the markup or post data. These field dependencies can be used with any Inputfield forms. That means you'll be able to use it not just in ProcessWire, but in FormBuilder, and via the API too. It's very simple to use from the API. All you have to do is specify a ProcessWire selector to either "showIf" or "requiredIf" to the Inputfield, and ProcessWire takes care of the rest: // show this field only if field 'subscribe' is checked $inputfield->showIf = "subscribe=1"; // show this field only if 'price > 0' and at least one category selected $inputfield->showIf = "price>0, categories.count>0"; // make this field required only if 'email' is populated $inputfield->required = true; $inputfield->requiredIf = "email!=''"; This feature will be in the 2.4 core (rather than as a separate module), so it will also be ready and available for things like module and field configuration screens.1 point
-
You probably have the HTML Entity Encoder text formatter turned on for the field in question. You will find this setting on the details tab of the field. Disable this to allow html to render.1 point
-
You might want to check the "Sort settings for children" in the Family-tab of the template which is assigned to the page that contains all the areas, the parent. Or you can manually set the sorting in your selector via code: http://processwire.com/api/selectors/ Under the section Sorting the results of a selector1 point
-
@horst, tnx for the image options (now in dev branch), sharpening look more then great !1 point
-
It's very unlikely such a search would be performed, but i caught it during some testing, so i guess it would be possible. Cache is not enabled and if i understand correctly GET variables are not cached anyway? Requiring the user to limit the search is a great idea though.1 point
-
OK if you really need the same iterators from the accordion, you might also iterate on your area page as well to get the same index as in the accordion: $i = 0; $iteratorInList = -1; // set the default -1 if not in list // "/areas/" being the url to the parent of your areas foreach ($pages->get("/areas/")->children as $area) { // find out if current page in loop is the same as current $page if($area == $page) { $iteratorInList = $i; break; } $i++; } echo $iteratorInList; Seems a bit cumbersome, but I don't know of a method like $somePage->index($list) ... similar to jQuery.1 point
-
Why not save the number or color on each page as data? echo $page->color; Or you can use $page->id for that too: .my-class-1234 { background-color: green; } .my-class-1235 { background-color: red; } in your accordion: <li class="my-class-<?php echo $child->id; ?>"><?php echo $child->title; ?></li> on your page: <body class="my-class-<?php echo $page->id; ?>"> </body> That makes you dependent on the id though, which is generated form the system, so maybe you can define your own identifier $page->myColorID; or something, and work with that.1 point
-
Either manually iterate an iterator variable within the foreach loop: $i = 0; foreach ($somaeArray as $item) { // your code echo "my-class-$i"; $i++; } Or you can deal with a for loop, and you can access your items in the page array like so: $selectedItems = $pages->find("your-selector"); $len = count($selectedItems); // or $selectedItems->count(); for ($i=0; $i < $len; $i++) { // so something with $selectedItems->eq($i); echo "my-class-$i"; } Edit: adrian kind of beat me to it =)1 point
-
Not exactly sure what you are after, but a typical approach to numbering is: $i=1 foreach($items as $item){ echo '<li>Item#' . $i . ': ' . $item->title . '</li>'; $i++; } Hope that helps. EDIT: Just saw your second post, and I don't think I really understood what you are looking for. It sounds like you want to generate the number via the admin, rather than on the front-end. Is that correct?1 point
-
I'm not sure I understood completely your question, but i'll try to answer. My interpretation is that you have a page with four children, and you want a link to each of the children with a correspondent image taken from that children. This depends on how the limit from your image field. If the limit is "1" the field will return one image, and the url can be called with "$page->image->url". If the limit is different from one the field will return an array of images, and we would return the first image with "$page->images->first()->url" or "$page->images->eq(0)->url". I will assume the last case: echo "<ul>"; // go through all children of this page foreach ($page->children as $child) { echo "<li>"; // print the url of the current child on the loop as the target of the anchor element echo "<a href='{$child->url}'>"; // print the url of the first image on the current child as the source of the image element echo "<img src='{$child->images->first()->url}'>"; echo "</a>"; echo "</li>"; } echo "</ul>";1 point
-
I don't think the voting opens till September, but you can still click "like" for ProcessWire, if you want to. That "like" system is the same one we use in the modules directory, and something I plan to release as a module soon.1 point
-
Greetings, netcarver: excellent first bullet point! I have a three-ringed binder filled with blank white paper that I carry around with me all the time. I use those paper dividers with the colored plastic tabs so each site gets it own little section, and I constantly add to pages and re-sketch little bits. I show my sketches to clients, sometimes redrawing elements right in front of them. I have tried so many mockup tools, but I have yet to find one that works as naturally as this. Thanks, Matthew1 point
-
Good pencil and the back of plenty of used envelopes (or a good notebook if your budget can stretch to it.) Vim (with vdebug) Github1 point
-
i think i might have tried snippets, but ended up with CodeBox which i'm finding really great... have tons of PW code samples and reference in it.1 point
-
Great addition, thanks ryan or building it and Antti/Avoine for sponsoring it! It can make several of my more complicated forms on some projects a whole lot shorter and more legible now And like many others, I marvel at how well ryan's initial versions of amazing features just seem to be so polished!1 point
-
This is epic. Thanks for building it Ryan. Couldn't be happier with how it turned to be!1 point
-
Hi Tester. Welcome to PW and the forums. Not sure what you want to achieve in the end but users in PW are also stored as pages. Hence, they come with a template. You can add as many fields as you like to the user template to store your data and retrieve and display these like any other field using your template file - hence extending "user". To view the "user" template, go to Setup->Template. Then under filters panel, under show system templates, select yes. Scroll down to the now revealed "system" templates. Select the "user" template and you are ready to start adding your custom fields to it . If you wish, you can then hide the system templates when you are done... About IDs, users are automatically assigned IDs when you create them Edited for clarity...1 point
-
OK, so I was able to reproduce this scenario: when you use PageTitleLanguage fieldtype with only default language installed, content of the Title field is not editable. Content does not change after page save. Problem is solved when you install more languages to PW. Maybe this thread should be moved to Multi-Language Support forum instead where we can discuss is this even bug since why would you need PageTitleLanguage field with only default language installed. Well, I did so because we will have different languages for the site in the future but first release will be only in finnish.1 point
-
Interesting topic, thanks for creating it Joshua. We have had similar talks since Drupal seems to be a platform that many organisations know in Finland. Big boys only talk about Drupal or Sharepoint. I have had my talks with our clients about "PW vs Drupal"... today I just do what Ryan once suggested: show them PW - build something quick, let them see how you develop with it and how quickly you can make things. You know you can build the whole backend of "events management" or "custom application never build before" in just about 30 minutes. Just build it. But if you do want talk about PW and Drupal, you should mention these things (I am by no means a Drupal expert and too lazy to check all the facts, so take this with grain salt and please do correct me if I am telling lies): Drupal release cycle is too fast for many. They try to get new major release every two year and only two latest are supported. Also major releases do break APIs, so probably most of the custom development need to be redone at least every four year. This might be fine on some projects, but for our clients that is usually an impossible schedule. It helps a little that new versions usually don't ship on time, though - and also some community efforts are trying to keep older versions secure. Ask people about their Drupal projects... most are not too proud of those: "This is little hacky" or "We didn't follow most of the best practices here, since we were in hurry". Those comments we got from the company, that we bought to teach us Drupal development and wanted them to show us their best work... Many people build sites with Drupal without really knowing how it works... which is understandable since it takes about 6 months to learn that beast (heard that 6 months estimate from CEO of biggest Drupal company in Finland and my initial feeling and personal experience suggest that it is pretty accurate). Drupal development is very different from normal PHP coding: If you (and your co-workers) have invested 6 months to "unlearn" PHP development and learned Drupal, you don't want to think about alternatives on that point. Drupal projects are expensive. In Finland ie. "The cost of Drupal web projects usually begins at about 20,000 euros, but projects best suited to Drupal generally cost more than 100,000 euros." (source: http://northpatrol.c...nal-products-2/). I usually draw a picture where PW is lots of tiny blocks, that cover 80% of needs and very little goes away. So you just build the remaining 20% and you get exactly what is needed. With Drupal (or any other "big" platform) you do get big block that goes well over 100%, but has more than 20% of holes. So you do have to build the remaining 20%, but also end up more than what is needed. So if you want to get rid of all the bloat, you do have more work to do. I have personally tried and wanted to learn Drupal for many many times. I always end up with big frustration and sites that were "nearly there". That was before PW, of course. EDIT: This was all very technical, so might want to talk this language only with tech orientated clients. With others, I would focus on PW admin usability and flexibility on frontend.1 point