Jump to content

ryan

Administrators
  • Posts

    16,772
  • Joined

  • Last visited

  • Days Won

    1,530

Everything posted by ryan

  1. The PagefilesManager::url() method is now hookable on dev. For high volume functions like this, I go a little further than just prepending 3 underscores and instead implement both a hooked and non-hooked version, just to reduce any potential overhead. Meaning, PW's hook system doesn't get called upon unless/until the function is hooked. Not sure it really matters, but it's just a minor optimization.
  2. Dragan, it sounds like you are attempting to use LanguageSupportPageNames in combination with another multi-language solution (appending language segments to URLs). These cannot be used together. You either need to use the solution you started with, or abandon it and switch to LanguageSupportPageNames. If you are going to use the multi-language solution you started with, which was to append language segments to the end of the URLs, then you should definitely uninstall LanguageSupportPageNames. Or, if you are willing to remove all of your code that has to do with getting/setting $user->language, or modifying URLs, in your template files, then you can use LanguageSupportPageNames. The important thing to keep in mind is that LanguageSupportPageNames does all the work for you, so you do not need or want to have any code for dealing with languages in your template files (unless making something like a language switcher).
  3. That error seems to indicate that the system has language support installed (i.e. there is an $languages API variable), but the user's language is not set. That's unusual for it not to be set, so I would check in your code to make sure you aren't manually setting $user->language to an invalid value somewhere.
  4. I ran my tests attaching them statically too, but it doesn't make a difference. I will try bundling them into a module (rather than anonymous functions from a template file) to see if it makes any difference. But two suggestions I have here are: 1) attach your hooks in an init() method, rather than _construct(). ProcessWire may still be booting when your _construct() is called. Though in this case, I doubt it makes any difference, but I would try that just in case. init() or ready() is typically where hooks are attached (initializing connections with external things), whereas _construct() is for initializing internal things. init() is called before the current $page is known, and ready() is called after it is known and available as an API variable. In your case, init() is the right one to use (though ready() could also be used). 2) after moving them to an init() method, switch to using non-static -- attach directly to $this->fields and $this->templates (the API variables). Static hook attachments are only necessary for objects that might have more than one instance, like Page, User, Field, Template, etc. But there will never be more than one instance of Fields or Templates, so you can benefit from slightly less overhead by attaching them directly to the API variables.
  5. I agree that repeaters are definitely not the way to handle an email subscription database. PW's database could certainly handle it, but it wouldn't be scalable at the UI level in the admin. A great way to handle user subscriptions is to make use of the tools provided by dedicated services like MailChimp or ConstantContact, etc. Another great way is to use FormBuilder, which will save your subscriptions in it's own database and let you export them to a spreadsheet for import at your distribution service. It will even let you cross-post them to your own database and your distribution service at the same time (depending on what service you are using).
  6. Here's what the code actually says. In the Page class, we have these constants: const statusOn = 1; // base status for all pages const statusLocked = 4; // page locked for changes. Not enforced by the core, but checked by Process modules. const statusSystemID = 8; // page is for the system and may not be deleted or have it's id changed (everything else, okay) const statusSystem = 16; // page is for the system and may not be deleted or have it's id, name, template or parent changed const statusHidden = 1024; // page is excluded selector methods like $pages->find() and $page->children() unless status is specified, like "status&1 const statusUnpublished = 2048; // page is not published and is not renderable. const statusTrash = 8192; // page is in the trash const statusDeleted = 16384; // page is deleted (runtime only) const statusSystemOverride = 32768; // page is in a state where system flags may be overridden const statusCorrupted = 131072; // page was corrupted at runtime and is NOT saveable const statusMax = 9999999; // number to use for max status comparisons, runtime only These are all the possible values for status. However, status is a bitmask, so it can have more than one value at a time. However, the status levels are ordered from most visible to least visible, so selectors like "include=all" actually translate to "status<9999999" and "include=hidden" translates to "status<2048". Next is the PageFinder class, which is where the "include=all" and "include=hidden" are defined, among other things. There is also an internal mode in PageFinder called "findOne" that is an option that the $pages->get() function uses. The findOne option is not one that you would use on your own, it's only an internal designation. The findOne option states that: 1) return only the first match; 2) skip over any access control checks; 3) limit to pages with status less than unpublished (unless another status is specified or include=all is specified). There is also the "findAll" option, which is what is assumed when you specify "include=all". That one states that 1) the status must be less than statusMax (meaning, it can include any available status); and 2) skip over any access control checks. Again, you don't need to remember what findOne and findAll are, since you won't ever use them. But I mention them just to explain how selectors translate in the system. $pages->get() or $pages->find() are not going to include pages in the trash unless you specify an "include=all" or one of the high status levels. $pages->get() is different from $pages->find() in these respects: $pages->get() only ever returns 1 page. $pages->get() bypasses access control and will include hidden pages. You don't need to specify "include=all" to $pages->get(); unless you want to retrieve an unpublished page or a page from the trash. If there are times when you want a $pages->get() that performs exactly like $pages->find(), except only returning one page, you can do this: $page = $pages->find("your selector, limit=1")->first(); if($page) { // you got it } Or you can do this: $page = $pages->get("your selector"); if($page->viewable() && !$page->isHidden()) { // you got it } I almost never need to do any this though (or necessarily even remember it). $pages->find() behaves the way I usually want it to, including things that aren't viewable and things that don't belong in lists and navigation. And $pages->get() behaves the way I usually want it to, returning the single specific thing that I asked for.
  7. Sounds good Steve, we look forward to seeing you around here. When you get to the point of trying to accomplish specific access control scenarios, post more and we can help you solve them.
  8. There hasn't ever been a "status=published" option in ProcessWire that I'm aware of. The status=published would simply translate to a "status=1", which basically means "any page." In this case, the "status=published" seems unlikely to be the source of the problem by itself… even if it isn't a valid option, it doesn't seem to affect the result in a way that would matter. Given that the code still qualifies the publish_until date later, I wasn't able to logically figure out how it could unpublish a bunch of pages, nor could I duplicate the issue myself. The only thing that seemed like a possibility was if the server's date got majorly screwed up, there could be a potential problem. Many servers do nightly maintenance services, and I'm wondering if one of them breaks the clock for a few seconds or something. That was the only thing I could think of?
  9. Thanks for trying it out. I didn't realize that locale settings went as far as typecasting. Seems like typecasting should be about maintaining a type for the language, not for display. While we could set the LC_NUMERIC, and maybe that's the right way to go (I'm not yet sure), I'd be worried about the situations when someone wants to override the numeric stuff. Perhaps FieldtypeFloat needs to do this in the sleepValue method: save the locale, set it to something compatible with PHP and MySQL, then set it back to whatever it was. That seems like maybe the way to add this with least impact.
  10. The PageAutocomplete can be used with a custom selector. If we're talking about a potentially huge list of pages, that's what I usually use. If needed, you can also set the "label" field to be "path", so that you are still aware of where a page is in the structure.
  11. Welcome to the forums Steve! In ProcessWire "superuser" is a special role that can do everything, regardless of any access/permission settings. Managing fields templates and users is typically the job of superuser. If you've got a non-superuser with "user-admin" permission, then they won't be able to edit or add superusers. But they'll be able to edit/add anyone else. Templates and fields are only accessible to superuser. Actually you could add a template-admin or field-admin permission to a user to give them access to these things, but the need is very rare. That's why these permissions are not included by default with PW. This is only the case if the user-admin is creating new roles and assigning them to templates. It doesn't sound like your user-admins would need that ability. Your admin user would have a role with page-edit permission, and you'd assign that role to any templates used by pages you want them to edit. Beyond knowing that "superuser" is allowed to do anything, ProcessWire doesn't necessarily know that one role is beneath another, and I'm not sure that it could unless you had some of your own logic to it. So you'd probably want to create your own front-end user tool for this, use hooks, or modify the behavior of the existing ProcessUser module. You can do this relatively easily by copying the existing /wire/modules/Process/ProcessUser.module to /site/modules/ProcessUserCustom.module, modify it to work the way you want it, and edit the page /admin/access/users/ and change the "Process" field on that page to your custom version of it. Though if the intention is simply to have the ability to add or delete users easily, I think a front-end tool (or your own admin tool) would be simplest. That's because you could take out the role considerations (less for your editors to think or know about), handling that automatically based on your needs. All of your access control scenarios seem within the scope of the system, except for the one that needs to know about one user defined role being considered above another one. But there are numerous ways to handle that, like mentioned.
  12. The PageArray part is called "type hinting" in PHP. It is the developers way of telling PHP that it should throw an error if it's given something other than a PageArray. That way the developer doesn't have to write extra code in the function to make sure it's been dealing with the right type of info passed to it before attempting to use it. For the consumers of the function (you and me), it's also useful just purely for readability and knowing what it expects you to give it. It's also nice to know that you'll get a consistent error immediately if you give a function the wrong info. Like if you passed in a Page rather than PageArray, you'd know right away, rather than trying to figure out for some time why the function isn't working. If we had a function that we wanted to accept multiple types, like say arrays, strings and ints, then of course we would not want to type hint like that. We would probably just have myfunction($something) instead.
  13. I'm trying to reproduce this so far, but can't. I added this code to my /site/templates/admin.php, but only get 1 message when I save a template or field: $templates->addHook('saved', function($event) { $this->message('Templates "saved" hook executed'); }); $fields->addHook('saved', function($event) { $this->message('Fields "saved" hook executed'); }); Are there any other factors, like other modules or is it possible your hook is getting attached twice?
  14. This was fixed, and localUrl() should be possible with 404 pages now too. Not to mention, multi-language 404 pages are supported as well. But you'd have to be running a dev version that is pretty new (I think this was pushed to the source a week or two ago).
  15. ProcessWire wants to have a local path to save files when you upload them. But using a solution like Teppo's, where you alternate the URL where they live, is certainly a possible way to redirect requests for any file to an alternate location. Another possibility is that I could make PagefilesManager::url() hookable, so that you could modify it with a hook. This would probably be the cleanest method, and I'll be happy to add the hook if anyone wants it. However, you would still need to be responsible for making sure that the files that live in /site/assets/files/* manage to find a way to their new URL location, whether it's literally having them copy to that location, or it's a directory mapped to another drive or server, etc.
  16. ryan

    20.000 massages

    I can't wait till we get to 50k massages. I wonder what WillyC will come up with for that event.
  17. Are you running an opcode cache (APC?). If so, put this in a PHP file and run it: <?php apc_clear_cache(); I have no idea if that's the problem. But any time I get weird/inexplicable behavior from PHP, that usually fixes it. If that's not it, then it seems like the only thing different about your module from others would be the name. Hard to imagine it could be an issue, but I would try renaming it, just in case. If not that: Turn off computer. Wait 30 seconds. Turn on computer?
  18. We have append() for consistency with jQuery. I also like the team of prepend/append naming (it sure beat's PHP's unshift/push terminology). But I also think the term "add" is ultimately more friendly, especially when talking about adding an item to a group of items. As a result, I tend to use add() when adding items and append() when moving things around. Ultimately they do the same thing, but one may be more readable than the other depending on the context. Use whatever you prefer.
  19. That's correct. Though you could bypass it by specifying your own selector for what pages should be selectable. But if you are specifying a "parent" then it's assumed you are making the children of that parent selectable. If you use an input type that supports hierarchy (PageListSelect or PageListSelectMultiple) then the parent is considered the starting point, and you can go beyond just the direct children.
  20. Very cool, thanks for sharing this with us. I've not had experience with a Raspberry pi computer before, but it sounds very compelling.
  21. That's essentially what the multi-language support solutions are doing. PW 2.4 doesn't change or add anything in this regard. Careful with use of the term "module" in this context, just because that means something different in ProcessWire (a plugin). And things like blog and search are not modules in ProcessWire, but things that you build with pages. However, you can restrict a search to any branch in the tree just by calling find() on the page that represents that branch, rather than $pages. For example: $pages->find("your selector"); // searches entire site $pages->get('/products/2013/')->find("your selector"); // searches everything below /products/2013/ $pages->get('/products/2013/')->children("your selector"); // searches only immediate children of /products/2013/ There are forum and shop modules (by @apeisa). But these are both labeled as "proof of concept" modules, meaning they are not necessary turn-key solutions so much as solutions for you to examine, learn from, build from, adapt to your needs. I also don't think that these modules are deigned for multiple-installations on the same site, but not positive. I'm not sure you need to let the needs of user accounts dictate the approach. I personally would be more inclined to isolate the user accounts from the sites for this particular need, perhaps running a separate PW installation that is dedicated to just managing the user accounts for all the domains. But I'm not really sure what the best route is without giving it more time. There are already forum solutions out there that people have spent years developing and making them the best. IPBoard is one of them. We couldn't duplicate that unless we also spent years doing the same. Regardless of how many forum solutions get built as ProcessWire modules, I don't see us moving away from a dedicated platform like IPBoard for this.
  22. I'm not really sure what the best solution is to this, and how many other locale rules we might have to potentially account for (if any?), but one solution would be for FieldtypeFloat::sleepValue to replace commas with periods. Do you want to try adding the following to your /wire/modules/Fieldtype/FieldtypeFloat.module, or replace with the attached file? public function ___sleepValue(Page $page, Field $field, $value) { if(strpos($value, ',') !== false) $value = str_replace(',', '.', $value); $value = (float) $value; return $value; } FieldtypeFloat.module
  23. This is a reply to a PM from @dragan that is a continuation of his question above. I'm copying my response here just in case helpful to anyone else. FormBuilder is multi-language capable, at least the latest version is. Make sure you have the latest from the support board. It does need the $user->language set to the right language ahead of time. Even though FormBuilder is multi-language capable, some people still choose to just create separate forms per language, so that the resulting form submissions go into separate locations. If your needs are diverse, you may find creating separate forms per language is still a good idea. But give the multi-language form option a try just in case. The only thing to mention is that "select" fields are not (yet) translatable, so avoid using them unless for numbers, etc. You can still use Page reference fields to handle multi-language selects though (the same way you would in PW's admin). I'm not totally clear about what multi-language solution you are using, but your forum post mentioned example 1. That has since been removed from the old location since Multi-Language page names are now recommended for the previous examples. However, I'm keeping the old examples here now, in case you still want to reference it. Assuming you are structured similarly to example 1, adding the language URL segment to your URLs is something you have to do manually. It could also be done with a hook, but I would stick to doing it manually until you know everything works. ProcessWire 2.3.2 uses the new method documented here, rather than the one in example 1. But that documentation won't be applicable unless you abandon the method you were using (example 1). So if you've already invested a lot of time in pursuing example 1, then you may want to stick with it. Because it detects the language from the URL segment, you need to make sure that you have URL segments enabled for templates where you plan to use it (Setup > Templates > your template > URLs > URL segments). You need to code in your template files to detect the language. For example: if($input->urlSegment1 == 'de') $user->language = $languages->get('de'); That would need to be done first thing. You may prefer to put code like that in a common/shared include file, so that you only have to write the code once. When outputting URLs to other pages, you need to include that language segment as well: foreach($page->children as $child) { $lang = ''; if(!$user->language->isDefault()) $lang = $user->language->name; echo "<li><a href='$child->url$lang'>$child->title</a></li>"; } That way when someone clicks on a link, the language will be retained in the URL, i.e. /contact/de rather than just /contact/ Ultimately, this method is kind of a pain next to the multi-language page names method, which does all the work for you, and lets you actually have translated URLs. But unless it's a very big site, I think you'll find the example 1 method to work just fine, so long as you keep in mind that you have to manage: 1) setting the language; and 2) making your URLs include a language segment.
  24. I've posted a new documentation section on how to use the multi-language page names / URLs in ProcessWire: http://processwire.com/api/multi-language-support/multi-language-urls/
  25. Looks good ffub! I don't yet have a mailchimp account, but this might be a good reason to get one. They are a PHP, Atlanta-based company too, after all. You can always used a "saved" hook (which gets called after a successful save) rather than "saveReady". Or you could use both, letting "saveReady" populate something that is later used by your "saved" hook. But the only way to grab a previous value before save is to pull it directly from the DB. i.e. SELECT data FROM field_email WHERE pages_id=$user->id
×
×
  • Create New...