-
Posts
17,100 -
Joined
-
Days Won
1,642
Everything posted by ryan
-
Line 46 won't work because that line only gets executed if you are booting PW from elsewhere. You'll need to do it after line 46, like like 48. Try this on line 48: $rootURL = '/~theameri/process/'; Let me know if that does or doesn't fix it. Once we find a way to fix it, I should be able to find a way to fix it in PW so that other people on a similar server setup don't run into the same issue. Though this appears to be a little bit different issue than we've seen before, but it appears to be a PW issue not a server one. As for mod_rewrite, the installer checks to make sure it's installed. If it didn't give you an error about mod_rewrite not being installed, then you should be good.
-
Looking great -- nice update!
-
Adam had an idea and preference for making PageEdit return to PageList after saving, and he posted a snippet to make it happen in the FAQ section (thanks Adam!). I followed up with an alternate way using a module (something that won't get wiped out during upgrades). Posting again here since this is the Modules forum so the original topic can stay in the FAQ forum. Also thought this was a good example of how to make a simple module to customize ProcessWire for your preferences. Once installed, every time you save a page, it'll return to the PageList drilled down to the page you were editing. Some people prefer this behavior (though I'm not one of them). To install, paste the following (or download the attached module) into /site/modules/RedirectPageEdit.module. /site/modules/RedirectPageEdit.module <?php class RedirectPageEdit extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Redirect PageEdit', 'version' => 100, 'summary' => 'Redirects PageEdit to return to PageList after save rather than edit again.', 'singular' => true, 'autoload' => true, ); } public function init() { $this->session->addHookBefore('redirect', $this, 'myRedirect'); } public function myRedirect(HookEvent $event) { if($this->process == 'ProcessPageEdit' && preg_match('{^\./\?id=(\d+)$}', $event->arguments[0], $m)) { $event->arguments = array($this->config->urls->admin . "page/?open=$m[1]"); } } } RedirectPageEdit.module
- 1 reply
-
- 1
-
-
Adam, good tip. The only potential problem I can see here is that when you upgrade that update will get wiped out. Here's a way to do it in an upgrade-friendly way. Paste this into a file called RedirectPageEdit.module in /site/modules/. Or download it from the thread in the Modules forum (I'm going to post the file there). /site/modules/RedirectPageEdit.module: <?php class RedirectPageEdit extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Redirect PageEdit', 'version' => 100, 'summary' => 'Redirects PageEdit to return to PageList after save rather than edit again.', 'singular' => true, 'autoload' => true, ); } public function init() { $this->session->addHookBefore('redirect', $this, 'myRedirect'); } public function myRedirect(HookEvent $event) { if($this->process == 'ProcessPageEdit' && preg_match('{^\./\?id=(\d+)$}', $event->arguments[0], $m)) { $event->arguments = array($this->config->urls->admin . "page/?open=$m[1]"); } } }
-
Hello, Thanks, and Question: How to Override InputFiueld error message
ryan replied to fmquaglia's topic in General Support
Thanks we could definitely use help with the Spanish translations. I hope to be at the point in a few weeks where we can start plugging in new translations, and I very much appreciate your help. -
Hello, Thanks, and Question: How to Override InputFiueld error message
ryan replied to fmquaglia's topic in General Support
Thanks for your feedback! Glad that you like ProcessWire so far! There are some features that aren't in PW yet due to it being a young cms/framework (and the issue Adam mentioned ), and multilingual features are one of them. But the good news is that it's already in progress and the current top priority on the roadmap. A new user, role and permissions system also accompanies this. Thanks, Ryan -
Hey Jim, getArray() is a lower-level internal method (inherited from WireData) that's not intended to be part of the external $page API (http://processwire.com/api/variables/page/). Instead, getArray() just returns a picture of what's loaded in the class at that time. So your workaround is actually a pretty good solution. But I think this may provide more what you are looking for: $a = $page->getIterator(); The above will return a PHP ArrayObject that you can iterate or index-dereference like an array. If you need a native PHP array, you can do this: $a = iterator_to_array($page->getIterator()); I think this might also work (though haven't checked to confirm): $a = (array) $page->getIterator(); Some fields will be objects (like Page references, files, images, comments). Most can be typecast as strings, which may be what you want to do in exporting a CSV. But if you want the full raw data for the field, you may want to look at doing this: <?php $a = array(); foreach($page as $name => $value) { if(is_object($value)) { $field = wire('fields')->get($name); $value = $field->type->sleepValue($page, $field, $value); } $a[$name] = $value; } That sleepValue() function essentially converts a field's data to the appropriate format for storage in a DB. That should leave your array has having only values consisting of strings, nulls, ints or arrays (no objects, hopefully). In addition to the data you get from the above, you may also want to add these into your CSV: $page->id $page-parent_id $page->templates_id $page->name $page->status $page->sort $page->sortfield (string) $page->template
-
Just checking, it looks like I don't have the ~= operator implemented with the file fieldtype -- I have just added it to the latest commit. But the *= operator was already implemented, so that one should already work.
-
The file fieldtype doesn't carry a fulltext index on the filename, but it does on the description. See if this works: report_color|report_style|report_file.description~=$s
-
I'm guessing one of those fields doesn't support the ~= operator -- What type of fields are: report_color, report_style and report_file?
-
I tried doing a test locally using "title|body~=white" and it worked for me on pages titled "white" as well as "white/blue". So the next thing to look at may be the fields you mentioned. What type of fields are report_color, report_style and report_file? All text fields? If report_file is a file field, you probably need to do report_file.description, otherwise it's searching the filename. Another thing to look at is the word and how MySQL is treating it. Is it at least 4 characters? Is it a stopword? MySQL has some limitations with fulltext indexes that make them really useful for searching sentences, paragraphs and documents, but less useful in some other instances. Though all can be adjusted in MySQL's settings. Though the only adjustment I've ever had to make to MySQL regularly is to set it to index words down to 2 characters rather than just down to 4 characters. Regarding stopwords: With fulltext indexes, MySQL doesn't index "stopwords", defined as words that are extremely common and not unique enough for search purposes. These are words like: and, get, thus, than, and a hundred or so others. Though "white" does not appear to be a stopword, so I don't think that's the issue. But if one of the stopwords appears in your selector that uses a ~= operator (or *= with a single word), the word is not used in the search .. unless custom stopwords are configured in MySQL and PW. The full list of stopwords can be found here: http://dev.mysql.com/doc/refman/5.5/en/fulltext-stopwords.html
-
The ~= and *= assume wildcard operations in selectors. They can be used for searching text, textarea and related fields. The ~= operator says to find all the words in the given copy (not necessary together), and the *= says to find the given phrase in the copy. The ~= operator assumes wildcard matches with any of the words you provide, so a search for "apple" will also match "applesauce", "applet" and "apples", and likewise for any other words in the selector. The *= operator is more restrictive in that it's looking for your words in a specific order. But if searching for only one word, both operators would produce the same result and work with partial matches. Where they differ is when your search includes multiple words. MySQL does not support wildcards with indexed content beyond this. But it does support more selective wildcards with non-indexed LIKE operations (with the "%" and "_" wildcards). We don't use those in ProcessWire at this time because they are very slow in MySQL. In fact, too slow to suggest they be used for everyday operations. LIKE operations require full table scans, so are not a good thing to hide the implementation details of in ProcessWire. However, you can still use them if your circumstance calls for it. Here's an example searching the title field using a LIKE operation: <?php $result = $this->db->query("SELECT pages_id FROM field_title WHERE data LIKE '%juice%"); $ids = array(); while($row = $result->fetch_assoc()) $ids[] = $row['pages_id']; $matches = $pages->getById($ids); That would return pages with a title field matching "juice", "applejuice", "orangejuice" and "juices". ProcessWire selectors can match "juices" from "juice", but can't match "applejuice" or "orangejuice" from "juice" because of the way MySQL fulltext indexes work ... the match has to start from the beginning. But performing a LIKE match is a slow process, so something I recommend avoiding unless the scale of usage is under your control. So while I agree with you that additional wildcard selectors would be nice, we can't go much further without abandoning MySQL for searches and using something like Lucene (which is written in Java).
-
How to handle video upload or integration with youtube/vimeo etc...
ryan replied to Sylvio's topic in General Support
A single textarea should be able to accommodate multiple embeds (at least, that's what I do). But if you want to keep them separate (which woud probably be more bulletproof for client use), setup a separate child page for each embed. Then your video page would just cycle through it's children to pull as many video embeds as it needs. To make it even more bulletproof for the client, make a separate video_embed template and set it to be the predefined template that is used when adding children to your video page (under Setup > Templates > Your Template > Advanced). -
The specs on what is considered a valid URL are apparently very broad. I've had the same experience in being a little surprised at what PHP's filter_var URL filtering allows. But apparently it is based on a defined ISO (?) standard. If you put some extended ASCII or accented characters in there, you'll see the URL filtering get involved. We may want to implement a more defined URL filter specific to just http/s (perhaps as a configuration option for this fieldtype). Also double check that you have relative urls turned off in the field's configuration, as it may help in this particular case (though not yet at a computer to test).
-
How to handle video upload or integration with youtube/vimeo etc...
ryan replied to Sylvio's topic in General Support
Embedded videos are easy: just create a textarea field and don't add any textformatters to it. Then the client simply pastes in the YouTube/vimeo/etc. provided embed code into that field on the page. All you have to do is output it in your template. For client uploaded videos (non embedded) you just create a regular file field. Your means of output in your template will depend on the video format and what you do with it. I usually advise clients to use an embedding service because it makes it so darn easy, and bulletproof. If you don't want YouTube/etc branded videos, there are some very good an inexpensive commercial video embed services that work the same way but tailored to you (I think screencast.com is one). However a regular file upload field in PW will be just as easy if you know the details of your video format and targeted player. -
Peter, looks good but not sure your uncacheAll() is doing anything here since the pages are already cached in $reports (PHP's garbage collector isn't going to unset them as long as there is a reference to them). But if you are running up against a memory limit, try placing a limit on the $reports: <?php $start = 0; $limit = 500; do { $reports = $pages->find("template=report, start=$start, limit=$limit"); if(!count($reports)) break; foreach($reports as $r) { $r->setOutputFormatting(false); $r->report_status_select = "123456"; $r->save(); } unset($reports); $pages->uncacheAll(); $start += ($limit-1); } while(1); Written in the browser, so code may not be perfect. Let me know if you still run up against any memory limits. Also in your earlier example: $c->client_status_select = $selectpage->id; You can also do just this: $c->client_status_select = $selectpage;
-
Sounds good, let me know if any issues turn up again.
-
Are these examples still not working? You may want to double check that your copy of PW is relatively up to date with the current source. If in doubt, you can always replace the /wire/ directory with a new one (along with /index.php and /.htaccess). Also, you may want to edit /site/config.php and set the line that says "$config->debug = false;" to be "$config->debug = true;". That will turn on stronger error reporting that can help a lot during development.
-
Where is this code going? Is it part of a template or used somewhere else? In templates, PW has something called outputFormatting turned on (unless you turn it off). Internally, all file/image fields are stored as arrays. But the file/image fieldtypes use this output formatting to convert a file array to a single file when you set the max files to 1. This is provided as a convenience for your templates. It's so that you don't have to think about arrays when they aren't relevant to your intended use. I've been assuming you are using this code in a template, but if you are using it somewhere else (like via bootstrapping PW separately) then that outputFormatting isn't going to be on by default. So I figured I should double check that we are talking about code in a template, just to make sure we're talking about the same thing? The other thing to look at is that the file/image field is actually populated. I didn't do that in the example, but here's how you would: <?php foreach($page->children as $artist_item) { $image = $artist_item->artist_image; if(!$image) continue; // no image, so abort $thumb = $artist_item->artist_thumbnail; if(!$thumb) $thumb = $image; $thumb = $thumb->size(100, 100); echo "<li><a rel='lightbox' title='{$artist_item->title}' href='{$image->url}'><img src='{$thumb->url}' alt='{$artist_item->title}'></a></li>"; }
-
Let me know what you want to do with the TinyMCE config, and I can help you determine what needs to be put in. If you find a better solution for a RTE than TinyMCE, let me know. I've experimented with quite a few, and as annoying as it can be, TinyMCE seems to be the most tolerable. Also, lightweight markup languages (like Markdown) are often a good alternative. The results they produce tend to age and scale better... if you can convince your client to adopt the syntax.
-
Adam, Good find. If you issued a get() or find() that includes a "parent=" portion in the selector that didn't resolve to a page, then it would return the homepage. This was due to an error in the PageFinder code that didn't differentiate between 0 (homepage's parent) and null (no parent). This has been fixed and the update committed to GitHub. Thanks for finding this. Ryan
-
Sorry my code example assumed we were dealing with a single image (due to the field name being 'image' rather than 'images'). I should have thought to post an example for both. If your 'image' and 'artist_image' fields are designed just to hold a single image, I would recommend converting them to that to reduce confusion. To do this, edit those fields, and set the "maximum files allowed" to 1. After you do that, the API will reference it as a single image rather than an array of images. Following that, the original code example I posted should work. If you want to keep them as multi-image fields, then you'd want to change that code example to this: <?php foreach($page->children("limit=32") as $folio_item) { $image = $folio_item->image->first(); $thumb = $folio_item->artist_thumbnail->first(); if(!$thumb) $thumb = $image; $thumb = $thumb->size(100, 100); echo "<li><a rel='lightbox' title='{$folio_item->title}' href='{$image->url}'><img src='{$thumb->url}' alt='{$folio_item->title}'></a></li>"; } The only difference between the above example and the original are the first two lines in the foreach(). They grab a single image out of the array, like this: $folio_item->image->first(), rather than just $folio_item->image. This is the same as doing eq(0) as in Adam's example, so use whatever syntax you prefer. @adamkiss: thanks for your replies here!
-
You are very close! The main issue that I see is that you are referencing $image in a context where it doesn't exist. See my comment in your code: <?php foreach($page->children("limit=32") as $folio_item) { if($folio_item->artist_thumbnail) { $img = "<li><a rel='lightbox' title='{$folio_item->title}' href='{$image->url}'><img title='{$folio_item->title}' src='{$thumb->url}' alt='{$folio_item->title}'></a></li>"; // $image is an uninitialized variable in the line above. Did you mean it to be $folio_item->image? } else if($folio_item->artist_image) { $thumb = $folio_item->artist_image->size(100, 100); // you could also solve it by just moving this line below above the "if" statement: $image = $folio_item->artist_image; $img = "<li><a rel='lightbox' title='{$folio_item->title}' href='{$image->url}'><img title='{$folio_item->title}' src='{$thumb->url}' alt='{$folio_item->title}'></a></li>"; } // Output the image echo "$img"; } Here's how I might recode it: <?php foreach($page->children("limit=32") as $folio_item) { $image = $folio_item->image; $thumb = $folio_item->artist_thumbnail; if(!$thumb) $thumb = $image; $thumb = $thumb->size(100, 100); echo "<li><a rel='lightbox' title='{$folio_item->title}' href='{$image->url}'><img src='{$thumb->url}' alt='{$folio_item->title}'></a></li>"; }
-
Looks like that is just a PHP notice because PW is in debug mode. But I did confirm there is an uninitialized var there. I think this may be my mistake. I have submitted a pull request to apeisa with a correction for this. I'm guessing that /about-us/ is already an active page on your site? Since you've already got a page living at that URL, that page is handling the request rather than the redirects module. To do that redirect, you'll want to edit that page's template and do the redirect from there, i.e. <?php $session->redirect("history/"); But that's not particularly reusable. I know on some sites, it is a common need to have a section page (like /about-us/) redirect to the first child page. If that's your need, you may just want to setup a new template called section-redirect (or something like that) and do this: <?php $session->redirect($page->child->url); That way it's reusable for similar needs on any other section page. Lastly, lets just say you wanted a generic "redirect" template that you could use on any page to redirect to any other URL. You'd want to create your template called "redirect" (example) and create a new field of type "URL", giving it a name like "redirect_href". Add your "redirect_href" field to your "redirect" template. Edit your "redirect" template to have code like this: <?php $session->redirect($page->redirect_href); Then set the "about-us" page to use your "redirect" template. Edit it and type in the URL you want it to redirect too, like "/about-us/history/", in this case. Then you can continue to reuse that redirect template anywhere else that you might need an existing page to redirect elsewhere. The value of the Redirects module is that it will handle redirects for pages that aren't in your site tree. But if the pages are already in your site tree, and you want them there, then you'd want to use one of the methods described above rather than the Redirects module.
-
I totally agree. The funny thing is that this feature was actually in Dictator CMS (ProcessWire from 2003). It was designed in part by the needs of a company intranet, where they had documents for employees about benefits and stuff. I'm not sure we can easily set it up at the field-level just because asset storage is currently provided at the page-level, and fields just get their asset storage location from their parent page. Plus, we already have a means of determining if the file should be protected: if a page lacks the "guest" role, then we can assume that it's files should be protected. That's because any page that lacks the "guest" role requires a login to access. So when a page is protected, it's asset storage dir would start with a period, i.e. /site/assets/files/.123/ rather than: /site/assets/files/123/ I'm thinking we'd do that rather than the /files-private/ mentioned in the previous message just because it strikes me as a littler simpler (simpler is better). PW's htaccess file already blocks access to any dirs that start with a period. But we'd update it so that requests that match /site/assets/files/.[0-9]/ would get sent to PW, which would perform the access checking before delivering the file's contents.