Leaderboard
Popular Content
Showing content with the highest reputation on 05/15/2013 in all areas
-
zyON, Check into the Page Fieldtype Maybe something like this for organization: Shoes -- Men ---- Product A ---- Product B ---- Product C -- Women ---- Product A ---- Product B ---- Product C Brands (these are just the references, no products listed as children) -- Brand 1 -- Brand 2 -- Brand 3 Collections (these are just the references, no products listed as children) -- Collection A -- Collection B -- Collection C Create page fields for Brand and Collection, and add them to your "Product" template. Now you can associate brand and collection with each product. So to get the output you need: Shoes > Men (Any Brand) $pages->get("/shoes/men/") Shoes > Brand2 $pages->find("has_parent=/shoes/, brand.title=Brand 2") Shoes > Brand2 > CollectionB $pages->find("has_parent=/shoes/, brand.title=Brand 2, collection.title=Collection B") You could also pass $input values to the selector so this could be generated via use selections.4 points
-
You can enable this option by editing your /site/config.php and setting $config->advanced=true; Next edit the template (Setup > Templates > edit) that you want to be able to change the createdUser. Click on the "system" tab (this is only visible in advanced mode). You'll see checkboxes for various options–check the appropriate one and save. Go back to your /site/config.php and remove the $config->advanced line you added earlier… as you don't usually want advanced mode on (some settings can be dangerous). But you should now have the ability to change the created user for pages using that template.4 points
-
A german presentation about ProcessWire: Video: (second half is PW) https://bambuser.com/v/3588985 Slides: http://wdcmdresden.github.io/treffen/24-knockout-und-processwire/processwire/#/3 points
-
That's what I assume he wants... If you want to know which is in the page array use filter. $found = $pageArray->filter("id=1001|1003|1005"); echo $found; // 1001|10033 points
-
I've now got ProcessWire (local dev) fully converted to PDO and running with both PDO ($database) and mysqli ($db) available to the API. When in the admin, the debug mode info at the bottom highlights queries from each, so that you can more easily identify mysqli queries that you may want to convert to PDO. As a matter of efficiency, ProcessWire doesn't actually initiate the mysqli connection until you access something from the $db API variable. Meaning, the core and a stock install of PW doesn't use mysqli at all (or attempt a DB connection through it), but it makes it available if any modules or your site want it. In order to achieve this, I had to abstract the existing mysqli Database class behind a passthrough gatekeeper class. The only way you will notice that is if you are using any kind of type hinting for the old Database/mysqli class, OR if you are using procedural mysqli functions. I don't think I've seen any modules type hinting the old Database class or mysqli except for my own (like Form Builder). But I do think I've seen procedural use of mysqli at least once (I think it might have been in one of Teppo's modules?). Anyway, not sure if this matters to anyone, but just in case, here's the things to watch for with mysqli: // If you are type hinting mysql or Database like this… function example1(Database $db) { ... } // this function example2(mysqli $db) { ... } // or this // …then remove the type hinting: function example1($db) { ... } function example2($db) { ... } // if you are using mysqli procedurally with a $db param: $result = mysqli_query($db, "SELECT COUNT(*) FROM pages"); list($count) = mysqli_fetch_row($result); // use it without specifying $db param… $result = mysqli_query("SELECT COUNT(*) FROM pages"); list($count) = mysqli_fetch_row($result); // …or better yet, use the OO version: $result = $db->query("SELECT COUNT(*) FROM pages"); list($count) = $result->fetch_row(); Since PW 2.4 will be backwards compatible in terms of the database, lets not worry about switching our 3rd party modules over to PDO until 2.4 is actually out in a stable version, which is still months away.3 points
-
I think changing the structure (like I suggested) would make it more efficient — even just from a product entry standpoint. Grouping by the largest set first (Men/Women) and then creating any references from there. You could setup the template to show brand / collection in the page list, or you could get all fancy with Page List Better Label2 points
-
2 points
-
This is awesome - I've been thinking about doing that for a while. So many great contributions - ProcessWire is destined for greatness!2 points
-
Hi valan, I see your point but I still think fields are the way to go. There are for certain some fields that are more often used, so you could group them together. Don't worry about the cars that do just hold a bunch of attributes, Pw scales well. You have more overhead with repeaters, because each repeater item is stored as page in ProcessWire. So with a car that has 50 attributes as repeater-items, you end up with 51 pages (1 car page + 50 repeater pages). You don't need to write 50+ lines of code, you can also loop through the fields of a page: foreach ($page->fields as $f) { // Maybe check for the value based on the type of field (select, page)... // if ($f->type == 'FieldtypeXY) ... $value = $page->get($f->name); if ($value) { echo $f->label . ' has value: ' . $value; } }2 points
-
My bad. All fixed now. My issue was I had set the limit = 1 for testing purposes. I increased it to 2 and it started working2 points
-
I don't see any reason to built your own users... rather use Pw users and assign them a different role + don't give them page-edit rights. You can add as many custom fields to the user template as you want. For the profile, you could just use a 'profile' template and display a form with all your fields from the user template. For adding users in the backend, you could do a simple Process module if you don't want to give your client access to add/edit users.2 points
-
2 points
-
InlineEditor 0.0.3 A simple, inline editor that allows you to edit text based content directly in pages themselves. Only use this to experiment. Please do NOT use this on live sites. 0.0.3 Updates Refactored process module Editor now shows result sent by server rather than a generic message New in 0.0.2 Editing repeaters work (actually always did from the beginning) All editor bar colours are now configurable through the admin panel All editable areas are now given a dashed border Few other fixes! Module page: http://modules.processwire.com/modules/inline-editor/ GitHub page: https://github.com/Sinmok/InlineEditor-for-ProcessWire Credits: Big thank you to apeisa for Fredi - whos Module inspired me to make this. It also provided a solid foundation on how to make my own module Ryan - For the whole CMS and the HelloWorld module which taught me how to hook on to page::render! Screenshots:1 point
-
Hi all! I want to create the Italian version of processwire site... Who want to join this project ? Every feedback is appreciated !1 point
-
Hats off RayDale - very impressive. No one has ever before written about the guts of processwire so sharp and so clear. On top of that you have put it in context with 2 main cms players drupal and wordpress and that increases the contrast of the whole picture even more !! This post should be put somewhere in the forum fixed and locked (Ryan) Let's not forget about newbies entering this forum repeating the same questions over and over. For them this post is an absolute must read and a real question and time saver.1 point
-
I agree with Reno, and it's even possible to keep the same url structure with url segments. edit: Well, Soma was right1 point
-
Yeah it's not (yet) on the Cheatsheet. No it does grab the pages by id as the name indicated ProcessWire never does grab the "whole" pages unless you need it or a field is autojoin. It's kinda lazy loading.1 point
-
Where do you want to add the page? If you want to add them under a parent with template 'company', you still need to check "add Children" in the templates Access options. Also make sure that you don't have any template family restrictions in the parents template.1 point
-
Cody Lindley strikes again http://tech.pro/tutorial/1214/javascript-regular-expression-enlightenment1 point
-
Well that doesn't really come through until now... So what now? If all of the "list" are in the PageArray (but also some others), or if the PageArray is the list 1:1... ? Now I'm curious why you want or need that? I would do that if you want to test if all of the list pages are in the PageArray: $result = $pages->find("template=basic-page"); $list = $pages->getById('1001,1002'); if(count($result->filter("id=$list")) == count($list)){ echo "all found"; }1 point
-
1 point
-
Reno, on your selectors, parent has to be "parent=/shoes/men/|/shoes/women/", or use the IDs, of course "parent=123|124"1 point
-
On the small chat window next to the video there is this guy "Philipp Pille Urlich" that seems to know a lot about PW1 point
-
German? What German? This is in English. Oh, wait a minute; that's Google Translational taking over! Nice presentation (slides); thanks for this. I love this translation on Page/131 point
-
...why didn't I see if something existed? Thanks dude, it works a treat. You are a legend!1 point
-
Sounds like a job for a module. There's a ton of material about module development around here, such as this Wiki article, that could be helpful for you in case that you decide to put it together. Then again, have you tried installing PixlrEditor module (https://github.com/PawelGIX/PixlrEditor) yet? Sounds to me like it already does exactly what you want..1 point
-
Awesome, I'll be using this with a couple of projects that are just winding up. I'll let you know if I come across any issues. If I find time I might try to go through and clean up that class too - there is a fair bit of unneeded code in there and lots of undefined variables. Thanks for your hard work on this.1 point
-
Nice! It didn't know you can do that. We definately need a markup guide and templating guide with different approaches. There are some great posts hidden in this forum. If only I could find some time to collect all that information.1 point
-
1 point
-
Not seen Flux before so will take a look. Vanilla has been around and is good for basic needs, plus it has a good-looking API I could easily look at the simpler ones - I know what you mean Antti and I do find that many forum features are simply not used or useful in larger software.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
-
Awesome news, congrats ryan! I nearly wet myself Must be a combination of ___smoothTalker() and ___giggity()1 point
-
Dear Ryan, Thanks for your answers! I appreciate it. Varnish caches images and pages in RAM, so it decreases server load and increases response time dramatically. With ProCache as the base, I think that Varnish would probably only become relevant when the server got hundreds of thousands of hits, but it's a good alternative to using a CDN. One can use Varnish to cache things up to a certain level of millions of pages, and then use a CDN like Edgecast when the page views are too much for Varnish on a standalone server to handle. I see ProCache in my future. Thanks again for building such an excellent system. Peter1 point
-
Not sure I understand the question–these are already static assets, what is there to cache? For something like images a CDN would probably be the next step, not a cache? Though note that ProcessWire does already cache image manipulations. So when you make an API call for an image at a certain size, that size gets generated only on the first call and a cached copy is returned for all later calls. They stay in their original location. They are already static assets, so no need to duplicate or copy them anywhere else unless for a CDN. ProCache hooks into all ProcessWire create/save/delete actions and makes adjustments to cache files as needed. So if you delete a page or change its URL, then the cache file for that page is deleted. ProCache also comes with a screen of config options for you to fine tune this further if you'd like. ProCache contains the rendered output produced by ProcessWire. For most sites, this is essentially a static HTML file for each cached page. It is the same thing as if you viewed a page on a website in your browser and clicked File > Save, producing a static HTML file.1 point
-
Ok so I gave it a shot with creating a module by altering Ryan's code you linked to and this seems to be working so far (I think). Here's the module using that code teppo linked to, slightly modified to match my requirements: <?php /** * Edit Yours Only * */ class EditYoursOnly extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Edit Yours Only', 'version' => 1, 'summary' => 'Custom module to allow users only to edit pages they created. Applies to role \'standard\'', 'author' => 'Christina Holly, TinaciousDesign.com', 'singular' => true, 'autoload' => true, ); } public function init() { if($this->user->hasRole("standard")) $this->addHookAfter("Page::editable", $this, 'editable'); } public function editable(HookEvent $event) { // abort if no access if(!$event->return) return; $page = $event->object; // criteria required in order to edit if($this->user->name !== $page->createdUser->name) $event->return = false; } } If anyone sees any problems that this could cause, please let me know. So far it appears to be working as I want it but I haven't tested it thoroughly. Thanks!1 point
-
You can configure the behavior of when the cache is cleared. But when you save a page, the cache is always cleared for that page, regardless of any other behaviors you've set. The other built-in options are to clear all children (and everything below), clear all parents (except homepage), clear homepage, or clear site. Another thing is that even a short 5-10 minute cache is hugely beneficial. That means that your page will only be rendered a max of once per 5-10 minutes, even if it gets hit thousands of times in that period. And the shorter the cache time, the less chance someone will ever see stale data. While I think we all have a tendency to make the cache time as high as possible (like an hour, a day, or a week), the right balance is often a much shorter time period. This would especially be the case if your site involved lots of page-to-page relations that fall outside of the tree relationship. Can you explain this a little more in detail. I'm on a shared Plesk Hosting Enviroment. This is not related to the hosting environment. Instead, it means that if you have code in your template files that is performing actions based on the hostname, then ProCache doesn't yet recognize that. For instance, if you are doing anything that checks $config->httpHost in your template file, you wouldn't want to cache that page with ProCache (or the built-in page cache, for that matter). This is an example of a template file you wouldn't want to cache: if($config->httpHost == 'de.domain.com') { $user->language = $languages->get('de'); } else { // www.domain.com // keep default language } However, I will be upgrading ProCache so that it saves the hostname with its cache files so that such a template file could still be cached.1 point
-
Perhaps even better: /** * Select random pages from a PageArray * * If no $seed is provided, today's date is used to seed the random number * generator, so you can use this function to rotate items on a daily basis. * * @param PageArray $pages the list of Page object to select from * @param int $amount the amount of items to extract from the given list * @param int|string $seed a number used to see the random number generator; or a string compatible with date() */ public function randomPages(PageArray $pages, $amount=1, $seed='Ymd') { if (is_string($seed)) { $seed = crc32(date($seed)); } srand($seed); $keys = $pages->getKeys(); $selected = new PageArray(); while (count($keys) > 0 && count($selected) < $amount) { $index = rand(0, count($keys)-1); $key = $keys[$index]; $selected->add($pages[$key]); array_splice($keys, $index, 1); } return $selected; } Now you can seed with a date()-compatible string, so you can rotate weekly (for example) using "YW", or monthly using "Ym", etc.1 point
-
I've updated renderList to include the pagerOptions here too in the dev branch. I've got to be honest and say that arrays in GET vars have always bothered me. They are so darn verbose and ugly. Why have a query string like this: var[]=1&var[]=2&var[]=3 When you can do this: var=1,2,3 All it takes is encoding your array like this: $input->whitelist('var', implode(',', $var)); and decoding it like this: $var = explode(',', $input->get->var); That's just my preference anyway, but not suggesting it should be anyone else's unless these things also keep you up at night.1 point
-
Thanks Nik, that did the trick! Here is the current version, which seems to work nicely. It duplicates the renderList() and executeList() methods until Ryan makes those two improvements to the renderList() method. This allows to search users (username requires direct hit, other fields use ^= operator). It searches those fields that are chosen from module settings (the same ones that are visible). You can also combine text search and role filters. To try this out, just install the module and then edit your /processwire/access/users/ page and change the process to ProcessUserExtended (page is locked by default, so open the lock). You cannot create new page with different name (like users-extended) and try it there, since ProcessPageType excepts to have pageName which is also fuel (like users, roles etc). Grab the code: <?php class ProcessUserExtended extends ProcessUser { static public function getModuleInfo() { return array( 'title' => __('Users extended', __FILE__), // getModuleInfo title 'version' => 100, 'summary' => __('Extended view for user management', __FILE__), // getModuleInfo summary 'permanent' => false, 'permission' => 'user-admin', ); } public function ___execute() { $out = ''; $wrapper = new InputfieldWrapper; $fields = $this->modules->get("InputfieldFieldset"); $form = $this->modules->get("InputfieldForm"); $form->attr('method', 'get'); $form->attr('id', 'userSearch'); $form->label = $this->_("Filter users"); if (!$this->input->get->roles && !$this->input->get->search) { $form->collapsed = Inputfield::collapsedYes; } $field = $this->modules->get("InputfieldText"); $field->attr('name', 'search'); $field->label = $this->_("Search"); if ($this->input->get->search) { $this->input->whitelist('search', $this->input->get->search); $field->attr('value', htmlentities($this->input->get->search, ENT_QUOTES, 'UTF-8')); } $form->add($field); $field = $this->modules->get("InputfieldCheckboxes"); $field->attr('name', 'roles'); $field->optionColumns = 5; foreach(wire('roles') as $role) { if ($role->name == "guest") continue; $attrs = array(); $this->input->whitelist("roles", $this->input->get->roles); if (is_array($this->input->get->roles)) { if(in_array($role->name, $this->input->get->roles)) { $attrs['selected'] = 'selected'; } } $field->addOption($role->name, $role->get('title|name'), $attrs); } $field->label = $this->_("Filter by role"); $form->add($field); $field = $this->modules->get("InputfieldSubmit"); $field->attr('value', $this->_("Search")); $form->add($field); $fields->add($form); $out .= $fields->render(); $selector = "limit=10, status<" . Page::statusMax; if ($this->input->get->roles) { $roles = new PageArray; foreach($this->input->get->roles as $roleName) { $roles->add($this->roles->get($roleName)); } if ($role->id) $selector .= ", roles=$roles"; } if ($this->input->get->search) { $fieldNames = implode("|", array_diff($this->showFields, array('name', 'created', 'modified', 'roles'))); $search = $this->sanitizer->selectorValue($this->input->get->search); $directHit = $this->pages->get("name=$search"); if ($directHit->id) $out .= "<h3>". $this->_('Found by username') .": <a href='./edit/?id=$directHit->id'>$directHit->name</a></h3>"; $selector .= ", $fieldNames^=$search"; } return $out . $this->renderList($selector, array("arrayToCSV" => false)); } public function ___executeList() { return $this->renderList("limit=25, status<" . Page::statusMax); } protected function renderList($selector, $pagerOptions = null) { $out = ''; if(!$this->pages->getTemplate()) { $form = $this->getTemplateFilterForm(); $out = $form->render(); } $table = $this->modules->get("MarkupAdminDataTable"); $table->setEncodeEntities(false); $fieldNames = $this->showFields; $fieldLabels = $fieldNames; foreach($fieldLabels as $key => $name) { if($name == 'name') { $fieldLabels[$key] = $this->_('Name'); // Label for 'name' field continue; } $field = wire('fields')->get($name); $languageID = wire('user')->language ? wire('user')->language->id : ''; $label = $field->get('label' . $languageID); if(!$label) $label = $field->label; if(!$label) $label = $name; $fieldLabels[$key] = htmlentities($label, ENT_QUOTES, "UTF-8"); } $table->headerRow($fieldLabels); $pages = $this->pages->find($selector); foreach($pages as $page) { if(!$page->editable()) continue; $n = 0; $row = array(); foreach($fieldNames as $name) { if(!$n) $row[$page->get($name) . ' '] = "edit/?id={$page->id}"; else $row[] = $this->renderListFieldValue($name, $page->get($name)); $n++; } $table->row($row); } if($this->page->addable()) $table->action(array($this->_('Add New') => 'add/')); if($pages->getTotal() > count($pages)) { $pager = $this->modules->get("MarkupPagerNav"); $out .= $pager->render($pages, $pagerOptions); } $out .= $table->render(); return $out; } }1 point
-
I would like to know a little more about your plans. Not sure if you seen my edit on your other thread showcase you site. I copied it to here: --- For your problem in managing images. Reading again you post, you want to have images in one place and select them on different pages? Or what are you needs here exactly? There's a simple way to archive something like this: Have an external section "files" where you upload images. But each image a separate page. Have a template "image" and add a single image field and may even more fields imaginable. So you could add a Page reference field "selected_image" that is set up to select from the section and only the "image" template. Add this field to your pages templates. Now you can select images/image using this field. You can manage images in one location and select it on each page. If you upload and replace an image the reference will not get lost, so this is a great solution. In the php template you would output the image using: <?php // if single page reference echo $page->selected_image->image->url; // if multiple page reference select foreach($page->selected_image as $img){ echo $img->image->url; } You even can select in TinyMCEs image PW dialog (select page, and chose image from that page), but this will add a path to the file and not an id reference, (which is my biggest problem with that approach). Though as long as you use it for out of TinyMCE content on page it's a great solution to have more control. It's also possible with a little hack (untill Ryan implemented this) to show a thumbnail in the page list select, if the label of the template is an image field (in template advanced setting available). Look this thread of mine: http://processwire.com/talk/index.php/topic,411.0.html1 point