-
Posts
16,762 -
Joined
-
Last visited
-
Days Won
1,529
Community Answers
-
ryan's post in Very strange Pagination behaviour was marked as the answer
Ian, I'm not sure what components of the URL correspond to each URL segment, but it looks to me like possibly the issue is urlSegment2 not urlSegment1. You've got lots of good URLs to test with there from that screenshot, so you'll want to make sure that when you access the page at a URL like that, you get a 404. That will solve the issue. Also, if you are only needing 1 level of URL segments, I would suggest doing your comparisons against $input->urlSegmentStr rather than $input->urlSegment1. For instance:
$fam = $input->urlSegmentStr; if(strlen($fam)) { if(!isValidFamily($fam)) throw new Wire404Exception(); $specieslist = $pages->find("template=species, limit=12, fam=$fam"); if(!count($specieslist)) throw new Wire404Exception(); $fam = $sanitizer->entities($fam); $metatitle = "British Moths | Thumbnail List by Family | $fam"; $title = "Families: $fam"; } Using $input->urlSegmentStr is better because it is inclusive of all URL segments. So if there are extra URL segments packed on to the end (like the bogus ones we see after the family names) then this will catch it, without you having to check $input->urlSegment2 separately.
For example, the $input->urlSegmentStr of the page accessed at /thumbnails/gracillariidae/ would simply be "gracillariidae". Whereas if accessed at /thumbnails/gracillariidae/some-bongus-junk, then the urlSegmentStr would be "gracillariidae/some-bogus-junk", which presumably your isValidFamily() function would be able to exclude.
-
ryan's post in pages created by api could not able to retrieve from other languages was marked as the answer
Hey guys, I think a few things in the code examples above need to be moved around. Also, since Repeaters don't know about languages, if you are creating repeater items on your own from the PHP side, you'll have to enable those items for all the languages they are applicable to. I replied on that GitHub issue report, along with suggestions for adjustments to the code.
-
ryan's post in Templates, namespace and modules problem was marked as the answer
If you've added "namespace ProcessWire" to the top of your template files, then you template files are now running in the ProcessWire namespace rather than the global one. AIOM runs in the global namespace, since it's not specifically made for PW3. Since AIOM uses static method calls to add files (if I recall correctly), you would just need to change those calls from "AIOM::something" to "\AIOM::something", with the leading backslash. That tells PHP to access something from the global namespace.
By the way, you don't have to disable compilation for templates individually if you don't want to. If you don't want the template compiler at all, just set $config->templateCompile = false; in your /site/config.php and the template compiler will be completely turned off.
-
ryan's post in PW 3 error with admin theme Modesta was marked as the answer
Okay if it works with 2.7.2 then it can be made to work with PW3. I installed it to take a closer look at what the issue was, and it came down to that PW3 doesn't support compiled admin themes at all. I'd forgotten that. I've updated PW3 to support compiled admin themes that live in /site/modules/, and that's now committed to the devns branch. Testing with AdminThemeModesta, it seems to work just fine. Though there's lots missing from AdminThemeModesta in terms of current feature support, so I'm not sure I'd recommend using it, but it should work now if you want it.
-
ryan's post in Search not working as intended? was marked as the answer
Tom, there's a setting in MySQL called ft_min_word_len and the default is 4. That means that if you have any word in your query that is less than 4 characters, MySQL won't be able to match it unless that setting has been adjusted (and you've forced it to rebuild the indexes on your db/table). That's why you aren't able to match "Disability Act", because "Act" likely falls under your ft_min_word_len. You should be able to get the result you are looking for by using %= instead. But since you want to match "disability" and "act" anywhere in your search, you'd need to do this:
template=document, title%=disability, title%=act The following code should use %= for words less than 4 characters and ~= for the rest.
$search = $input->get->text("search"); if($search) { $selector = ''; $parts = explode(' ', $search); foreach($parts as $key => $part) { if(strlen($part) > 3) continue; // use MySQL LIKE for words under 4 characters in length $selector .= ", title%=" . $sanitizer->selectorValue($part); unset($parts[$key]); } if(count($parts)) { // use MySQL fulltext index for words 4 characters and higher $selector .= ", title~=" . $sanitizer->selectorValue(implode(' ', $parts)); } $results = $pages->find("template=document" . $selector); } else { $error = "Please enter a search term in the search box above."; $results = null; } Come to think of it, it might be nice if PW just did this for you automatically when it detected the condition... but we don't know what the ft_min_word_len setting is.
-
ryan's post in get() requests not subject to access control was marked as the answer
When using PW's API, you should always consider your code to be operating as a kind of superuser, just like in PHP. In find() operations where you are retrieving multiple pages that you don't know exactly what they will all be, it's a sensible default to exclude "hidden", "unpublished" and no access pages, unless you request otherwise. This is there as a matter of convenience and pagination, not security. Of course you can override that (when you want to) with the "include=hidden" or "include=unpublished" or "include=all" options. Whereas with get() you are being very specific about what you want–a single specific page. Otherwise why would you get() it?
Neither find() or get() are intended as a primary means of access control–we have other methods for that (see below). They are methods setup to operate in the most common use cases and keep your API calls as short and simple as possible. Just because find() filters out hidden, unpublished and no-access pages by default does not mean you should count on it for access control. That's because the pages excluded from a find() don't include runtime access control, just that which is stored in the DB. Further, the behavior of whether or not a no-access page shows up in a find() result (that isn't overridden with an include= directive) is configurable with template access settings. Granted, in most cases find()'s defaults are giving you exactly what you want in terms of excluding pages the user can't view (for your convenience), but that's not the entirely of PW's access control, which supports runtime hooks. PW's job is to provide access control for the request, but not for your own code, that's the developers job. PW intends to give you, the developer, access to everything (like you would with jQuery and the DOM), and you decide whether or not it should be available for output. PW provides you with some handy access control methods to help with this:
$page->viewable(); // is the page viewable? true or false $page->viewable('field_name'); // is the field on page viewable? true or false $page->editable(); // is the page editable? true or false $page->editable('field_name'); // is the field on page editable? true or false If you want to have you own get() and find() that operate under different defaults, this is easy to do with hooks in your /site/ready.php file. For instance, this would add a $pages->one("selector"); method that automatically does a viewable() check for you and returns a NullPage() if the page is not viewable:
$pages->addHook('one', function($event) { $page = $event->object->get($event->arguments(0)); if($page->id && !$page->viewable()) $page = new NullPage(); $event->return = $page; }); Would there be value in adding a method like the above to our $pages API by default? Maybe. It wouldn't benefit my own API use, because the only time I use $pages->get() is because I want to get something without conditions. But if it would be super handy for others I'm happy to add it. Here's another example, lets say you want a method in $pages, like $pages->all("selector"); that always returns all pages with "include=all" implied:
$pages->addHook('all', function($event) { $event->return = $event->object->find($event->arguments[0], array('include' => 'all')); }); -
ryan's post in PW version displayed on the backend login screen was marked as the answer
Makes sense to me, I'll move that <?php endif; ?> down one line, so that the name/version only appears when logged in.
-
ryan's post in Valid URL error in PW 2.7.2 was marked as the answer
Testing here with PW 2.7.2 in a new URL field I setup called "href", I used the URLs you mentioned. For my field settings, I have "Allow single/double quotes" set to true, and for "Text formatters" I have "HTML Entity Encoder" selected. I tried with and without the "allow IDN" option, but it doesn't matter here since we're not testing with IDNs. Here are the results I got:
https://en.wikipedia.org/wiki/Peter_O'Toole
Input to URL field in admin: https://en.wikipedia.org/wiki/Peter_O'Toole API code to output: echo "<a href='$page->href'>test</a>"; Output in rendered page: <a href='https://en.wikipedia.org/wiki/Peter_O'Toole'>test</a> Result: Clicking the link works, taking me to the page on Wikipedia https://upload.wikimedia.org/wikipedia/commons/5/53/Peter_O'Toole_-_1968.jpg
Input to URL field in admin: Input to URL field in admin: https://en.wikipedia.org/wiki/Peter_O'Toole API code to output: echo "<img src='$page->href' />"; Output in rendered page: <img src='https://upload.wikimedia.org/wikipedia/commons/5/53/Peter_O'Toole_-_1968.jpg' /> Result: Picture of Peter O'Toole Basically, it's working exactly how it should. My best guess is that it wasn't working for you because you've got some other code in there somewhere HTML entity encoding the URLs, to make up for the bug prior to 2.7.2 where text formatters weren't being properly applied to URL fields.
Another possibility, check if your $page possibly has output formatting turned off? It would need to be ON for this all to work.
That's interesting, so it looks like the URL is getting URL encoded, converting the apostrophe to a %27. I did try entering that too, but PW converted it back to an apostrophe and then entity encoded it, resulting in the same working output as in my second test above. If this is literally how your URLs are stored in the database, then my best guess is that when you are outputting the value, either the $page's output formatting is off for some reason, or the HTML entity encoder wasn't selected in your "text formatters" details tab, which would prevent a URL with an apostrophe from working, whether it was URL encoded or not. I would suggest upgrading again to 2.7.2 and double check all your settings, especially the one about allowing single/double quotes and the Text Formatters. If the URLs are still not working, then check to make sure in your template file that the page's output formatting is enabled, like this: if($page->of()) { echo "<p>Output formatting IS enabled</p>"; } else { echo "<p>Output formatting IS NOT enabled</p>"; } If it's not enabled, you'll want to track down where you are turning it off, typically with a $page->of(false); or $page->setOutputFormatting(false); Finally, check that you don't have something else entity encoding the URLs in your site. If you've got a line like this, you'll want to remove it: $page->bfd_image_from_url = htmlentities($page->bfd_image_from_url); // avoid this -
ryan's post in Selector returns odd results was marked as the answer
You can use "|" to OR fields, or OR values, but not expressions. Your selector is translating to something you didn't intend. I think the selector you might be attempting is instead this:
template=event, enddate>=2015-11-06, enddate|startdate<=2015-11-13 Or you could use OR-groups:
template=event, enddate>=2015-11-06, (enddate<=2015-11-13), (startdate<=2015-11-13) Either of the above selectors says:
The template must be event. AND The enddate must be greater than or equal to 2015-11-05. AND (The enddate must be less than or equal to 2015-11-13 OR the start date must less than or equal to 2015-11-13). -
ryan's post in Exact illegal copy of my Site on another Domain was marked as the answer
If you upload a random txt or html file to your web server, can you access it at the other domain? My guess is yes. If so, it sounds like an honest mistake. Perhaps you are on a dedicated IP and the owner of the other domain made a typo when setting up their DNS record. Or perhaps the web host made an error when setting up their VirtualHost directives in Apache. You should be able to correct the problem by adding this to your .htaccess file somewhere after the "RewriteEngine On" line:
RewriteCond %{HTTP_HOST} !^www\.yourdomain\.com [NC] RewriteRule ^ http://www.yourdomain.com/ [L,R=301] -
ryan's post in How to translate admin dropdown menu's from a module? was marked as the answer
I'm assuming this is a Process module, since that's the only one that supports nav arrays. The arrays provided in your getModuleInfo (like the 'nav' array) are not called at runtime, instead they are stored in the DB. As a result, there's no reason to make those labels translatable–actually you should avoid it, otherwise the wrong language translation might end up stored in the DB. Instead, just make them regular strings like 'Enter Order' rather than __('Enter Order'). Then, somewhere else in your module, make them translatable. It can even be in a PHP comment. For instance, you could add this at the top of your module file:
/* * __('Enter Order'); * __('Enter User'); * and so on... * */ These should be in your 'default' language. Make sure the phrases are identical to those in your 'nav' array. Doing this just ensures that the language parser knows they are translatable phrases. After making that change, do a Modules > Refresh, then go back and translate the file (Setup > Languages > language > your file), and save.
Now it should work. If using AdminThemeReno, it won't work, unless you upgrade to the latest dev version. I just fixed that issue in AdminThemeReno yesterday actually. Since it looks like you are using Reno, you'll want to grab the latest dev branch.
-
ryan's post in Select Options Fieldtype (FieldtypeOptions) was marked as the answer
@ro-bo thanks for the detailed instructions. I was able to duplicate it after following the steps in those instructions. And @LostKobrakai was right that there was a missing getBlankValue in the sanitizeValue method. This week's PW dev version will include this fix at the top of sanitizeValue:
if(empty($value)) return $this->getBlankValue($page, $field); -
ryan's post in "pro" Support if agency license - multiple users possible? was marked as the answer
@Webrocker the Agency support/upgrades period should last for 1-year, regardless of whether a renewal or not. If you find that not to be the case, please let me know and I'll update your account to correct that. Though I'm not sure which account we are talking about, as you mentioned it was one separate from yours? Also, to add you to the Agency support, just have the purchasing account send me a PM indicating what other accounts they want to be attached to the support, and I'll be happy to add. Thanks.
-
ryan's post in Need help deleting an empty field from a template with 2 million+ pages was marked as the answer
If this were a files/images field and you had 2m pages of data, you might have to take extra measures. But from what I can see, you are just removing an integer field. ProcessWire should be able to do this quickly, so long as you are running an up-to-date version. What version are you running?
Have a look in /wire/core/Fields.php at the method ___deleteFieldDataByTemplate(). That's what is executing this. It has two options, the slow one, and the fast one. The slow one cycles through each page with the field and asks the Fieldtype module to handle the deletion. This is required for fields that have other assets that might need to be deleted too, like files or images. But for a field like an integer, it can use the fast method, which goes directly into the database and deletes it all with one query (which should just take a second).
My guess is that the version of PW you are running is old enough to only have the slow method, or that for some reason or another the slow method is getting used when it shouldn't. The slow method would almost certainly fail in trying to deal with 2m pages, so I'm pretty sure that's what we're seeing here.
So check your PW version. You may be able to resolve this simply by upgrading. If that's not it, let me know and we can look at other options.
-
ryan's post in How to delete "permanent" module was marked as the answer
You should be able to set permanent=false in your module info, and then in your admin do a Modules > Refresh. But if that doesn't do it, you could always update the 'flags' column for that module to be 0 (in the modules table), and then after a Modules > Refresh it should definitely let you uninstall/remove it.
-
ryan's post in New Options Fieldtype was marked as the answer
Categories are really a perfect use case for pages rather than options. But to answer your question, this should do it:
$options = $fieldtypes->get('FieldtypeOptions')->getOptions('categories'); foreach($options as $option) { echo $option->title; } This also works:
$field = $fields->get('categories'); $options = $field->type->getOptions($field); If you are going to be using the selections for anything, use the $option->id property, rather than the title, just in case you later go back and change the title or something.
-
ryan's post in [RESOLVED] Why am I getting this error? "no site configuration or install.php available" was marked as the answer
Glad you figured it out. Unfortunately $_SERVER['SERVER_NAME'] can't always be relied upon because some cases have it populated with something other than the hostname of the current site (like the hostname of the server itself rather than the site). Though you also can't rely on $_SERVER['HTTP_HOST'] either, as that can be manipulated by the request. If you need the capability to automatically switching DB configs depending on dev or live, your best bet is probably to copy your /site/config.php to /site/config-dev.php and only keep that file in your dev environment. Your /site/config.php will be ignored when /site/config-dev.php is present, enabling you to accomplish the same thing you are now, so long as you don't upload config-dev.php to your live site.
-
ryan's post in [Pagination] pageNumUrlPrefix not in all profiles? was marked as the answer
Actually pretty much everything has been moved to /wire/config.php, leaving /site/config.php exclusively for things that you want to modify from the defaults. You'll notice that /site/config.php pretty much contains nothing now other than debug and the settings added by the installer. However, any config property can still be modified from your /site/config.php file. See the /wire/config.php for a full reference of all possible properties you can customize.
-
ryan's post in processwire 2.5, when? was marked as the answer
We're aiming for soft launch this Friday and official a week later. Tried for last Friday but still had some issues to resolve + waiting on some things. I believe it's safe to start using now, but you'll still want to upgrade when 2.5 is official.
-
ryan's post in Problem with CropImage field was marked as the answer
xorotle, I've not been able to duplicate this, though have tried a couple of times now. As far as I can tell, CropImage is working well with the latest dev version (2.4.18). What version of PW are you using? The line numbers you indicated don't line up with more recent versions of InputfieldFile. So I'm wondering if you might be able to solve this one by upgrading to a newer ProcessWire. Also double check that you've got the latest CropImage as well.
-
ryan's post in Upgrading 2.5 dev versions was marked as the answer
Good points from Horst.
On my sites I just replace the /wire/ directory with the new one. Actually I rename the old one to ".wire" (or something like that, just in case I need it back… never have though) then put in the new one. PW automatically takes care of any database changes, so you don't need to worry about that. Also, if it needs an .htaccess or index.php update, PW will tell you the next time you login to the admin superuser account. So I wouldn't worry about replacing anything but /wire/ unless PW starts harassing you about it. The htaccess change Horst found above only matters for the installer, which isn't applicable on a site upgrade.
-
ryan's post in Site Crash was marked as the answer
What version of PW? I can't say as though I've ever seen tables get corrupted like that. But since you've got corrupted tables, you might also have a corrupted file system. I think Adrian's suggestion to replace your /wire/ directory is probably a good one.
Have any new modules been recently installed?
In your /site/config.php enable debug mode (change the line that says $config->debug=false; to $config->debug=true). You should now get a more detailed error message. Paste in the entire error message here if possible.
You mentioned that you cleared out your "assets" folder. I'm hoping that you cleared out your "cache" folder in assets, and not the entire assets folder? Still it shouldn't be necessary to clear out the cache folder.
Most likely something is still corrupted in the database or on the file system. You may want to export your entire database and re-import to a new database, then update it to point to that new database in your /site/config.php file (at the bottom). But while you are in PhpMyAdmin can you look at the list of tables and confirm that you have a "field_roles", and a "roles" table, both populated (not empty)? The error message you are getting makes me wonder if something is missing there.
-
ryan's post in Why does $session->login() require $session->redirect()? was marked as the answer
Both guys here are correct. The session needs to be regenerated with a new session ID and some new cookies need to be set, etc. Redirecting after successful login ensures you are dealing with the new and authenticated session and $user, ready to work with.
-
ryan's post in Users getting logged out after redirecting back from payment gateway was marked as the answer
I have no idea why users are getting logged out in your case, but a few things I would look at:
1. How long was the user logged in at your site? Make sure they have completed at least one full page request as a logged in user before you redirect them elsewhere. You can accomplish this by redirecting to a local page first before redirecting to another site.
2. What URL does your payment gateway return them to? If the user started out on an http URL and returned on an https URL (or the reverse), that might be something to look at. What sort of switching between http and https does your site perform?
3. Is the user returning to the exact same hostname? i.e. www.domain.com and not domain.com ?
-
ryan's post in Local development and remote assets was marked as the answer
Another option would be to add a small module that hooks Page::render and replaces the paths directly in the output... when running on localhost. It could replace it with something like this:
public function init() { if(wire('config')->httpHost == 'localhost') { $this->addHook('Page::render', $this, 'hookAfterPageRender'); } } public function hookAfterPageRender($event) { $event->return = str_replace('/site/assets/files/', 'http://domain.com/site/assets/files/', $event->return); }