Jump to content

ryan

Administrators
  • Posts

    17,140
  • Joined

  • Days Won

    1,657

Everything posted by ryan

  1. What I've extracted is that you don't like statics. You've set a goal of avoiding statics at all costs. And that's fine--I understand your reasons. I'm middle of the road on statics--I avoid them, but not at all costs. There is a reason they don't appear in PW's public API. But if they are the best fit for a given situation, given all factors, then I'd consider it a bad choice to use something else. We've got very good reasons for using them where we do. I hope you can understand why we wouldn't abandon an interface that works very well for us just because one person doesn't like statics. What I wrote in my previous message was that I support your ideas, but as an alternative method of configuration, not as a replacement. Step out of the ivory tower and propose something tangible and realistic. Use some code. For instance, I understand you'd like to have a separate class to handle configuration. I like this idea for many situations. So how would you formalize that in code? What specific methods would be in the ModuleConfig interface or abstract base class? How would you propose relating the configuration class to the module class? I'd suggest that it could be done by an agreed-upon class name, like "Config[ModuleName] implements ModuleConfig", or a module's getModuleInfo() could specify it's configuration class in it's info array. But maybe there's more ideas too. Get some momentum going here and maybe we'll have something we can commit to the code base now rather than later. I understand why it matters in many situations. But this distinction does not matter in ProcessWire modules. Can you think of any instance where it does? We go out of our way to keep these considerations away from those actually using the module. I don't yet know much about Laravel, so can't knock it or praise it. But I was turned off by the syntax I was seeing in the examples. Though I can find plenty to like after a quick look too. But it does seem like a lot of people are treating Laravel as God's greatest gift to PHP. So far I don't understand. Maybe there's something to learn here, even if there is some to dislike as well. While I don't hate statics like you do, I do agree in general -- I don't much like seeing them in APIs. That's why you don't seem them in ProcessWire's API.
  2. In real usage, ^= and $= just aren't that useful when paired with a fulltext index, because fulltext indexes store words, not partials. I actually cant think of any situation where the old fulltext implementation for those is worthwhile. I dont think anyone was using them, as a result. The %^= syntax is far more useful. But I don't want to have something as cryptic as %^= and %$= being part of our official set of operators... Would rather leave it as undocumented and eventually deprecate it, and let ^= and $= take the behavior. That's really how they were supposed to behave in the first place. So that change you linked was my attempt to correct the behavior of those.
  3. You should also be able to retrieve them via just $field->tags or $template->tags
  4. There isn't a page like this that exists in the system unless you are an admin and can view user accounts in Access > Users. However, you certainly could create a template on your front-end that does something similar. You can iterate all users by: foreach($users as $user) { // ... } You can retrieve any user by: $u = $users->get(123); // user ID; or... $u = $users->get('ryan'); // user name Here is the $user API which shows you what you can do once you've located the user you want to display.
  5. I think it just depends on what you are trying to do. But as a guideline, only consider using your own custom tables if the data you are pulling doesn't need to be represented by unique URLs. Pages are designed to be represented by URLs, though they don't always have to be. But if you've got complex data that is large in quantity or fields, and individual records don't benefit by each having their own URL, then you may find it more efficient to use alternate data storage like SQL (if you are comfortable doing so). If you want the data to be managed in ProcessWire admin and queried from PW's API, you can create custom Fieldtypes by extending Fieldtype or FieldtypeMulti. An individual Fieldtype can represent as complex of a table structure as you want it to.
  6. A page does not need to have two parents of the same generation like we do. In the case of ProcessWire, all pages are female.
  7. Biorn, here's some more info about LazyCron: http://processwire.com/api/modules/lazy-cron/ Ultimately, it's lazy, which you will notice if you don't have consistent traffic to your site. So if you need something to run every 5 mins consistently, then you should either use regular cron (from your server) or use regular cron to ping a non-cached page on your website (thus triggering Lazycron).
  8. I don't think there's a way to reliably change system paths after bootstrap has occurred. I also don't recommend trying it, just because it seems like there's potential to break things by doing that, and it may work in some cases and not others. Ultimately it wasn't designed for runtime changes to system paths. It probably works from $config.php just because all that happens before bootstrap. It is however designed for runtime changes to template paths via the $template->filename = '...'; syntax.
  9. I'm guessing you don't like Laravel much? There is a reason why statics exist as a language construct, and there is a reason why we use them where we do. Though our usage is admittedly rare, there has never been a goal to "avoid statics as much as possible". The goal has been to use the tools available to us to make ProcessWire as simple, flexible and extendable, to the intended audience, as possible. It's not often that we have use for a static method in ProcessWire, but when we use them it's because they are the most appropriate solution. Keep in mind, we don't actually "need" static methods. We could certainly do without them. They just make a whole lot more sense in our context than the alternative. It's important to realize that Module is just an interface for communication between ProcessWire and the functionality you want to provide. It is not a class or even an abstract class. It provides no implementation for you (other than what you might optionally choose to extend from some other class). The only requirement for a module is that ProcessWire can ask it what it is. That comes from the Module interface's 1 static method: getModuleInfo(). Without that, it is not a Module. The ConfigurableModule interface has 1 static method: getModuleConfigInputfields(), which you can choose to delegate elsewhere if you choose. Beyond the obvious benefits, these methods are static for correctness: they are about all instances, not a specific one. The existence of the interface is not a suggestion that you implement everything in the class itself. That's entirely up to you. If the scope or philosophy of your need is such that you want to split every part of it into separate classes and files, then you should (this is what I do in FormBuilder). The Module interface facilities this. But the reality is that most modules are not of that scope, and there's rarely a tangible benefit in our context to being more verbose. But we ultimately leave that choice to the developer. A module is a singleton only if the developer specifies "singular" in his/her module definition. Otherwise you will get a new instance every time you ask for a module. I understand what you are trying to get at here. There may be someday when the configuration needs of modules increases in scope to the point where we might benefit from such an approach, but we're not near that yet. In the present, I think the majority of module cases benefit more from less verbosity and the current approach. We already have the door open to this approach, even if it's not implicit--FormBuilder uses something very similar, for example. But I would be happy to support this more implicitly as a second option for module configuration in the future. Instance types are not loaded before they are needed. They are loaded on-demand, unless the module's definition specifies "autoload". ProcessWire caches its module information so that it doesn't need to even include a module's file until ready to instantiate. It's the module developer that should make the call about whether their module is designed to be singular or multi-instance. A singular module might very well be coded differently than a multi-instance one. I don't want the consumer to have to think about this variable. I'm not opposed to making architectural changes in major releases so long as they are geared at make things simpler or easier for the users of the software. While I don't share all your opinions on how some things should work, I appreciate and respect them, and am especially glad for your interest in them. If we were to implement an architectural change to make module configuration more implicit to a separate class, I'd support it (after all, it's an approach I already take in some modules). But it would be added as an option, rather than a replacement. In terms of future major releases, I don't like breaking backwards compatibility unless absolutely necessary. But if there's a net benefit to the wider audience, then I have no problem with it. The only thing in my mind that carries that status right now is the switch to namespaces in 2.4 (and the changes that would go along with it), which I'm looking forward to collaborating on.
  10. How about: $level = count($page->parents);
  11. $_SERVER['DOCUMENT_ROOT'] would have to be the same as $config->paths->root in order for that to work. Usually they would be, but sometimes they aren't, whether due to a subdirectory install or aliases/symbolic links. You'd probably want to set it like this instead, which should work (unless I'm forgetting something): $home->template->filename = wire('config')->paths->root . 'basic-page.php'; Also, since your basic-page.php is not protected by PW's .htaccess, put this at the top: if(!defined("PROCESSWIRE")) die('No access');
  12. 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.
  13. What is your /path/to/file.php? Here's the actual code from Template::setFilename that gets executed when you do $somepage->template->filename = '/path/to/file.php'; protected function setFilename($value) { if(empty($value)) return; if(strpos($value, '/') === false) { $value = $this->config->paths->templates . $value; } else if(strpos($value, $this->config->paths->root) !== 0) { $value = $this->config->paths->templates . basename($value); } if(is_file($value)) { $this->filename = $value; $this->filenameExists = true; } } Look at the "else" condition above, which is what's enforcing your template file to be somewhere below PW's root installation dir.
  14. Very interesting and unique--I like it! I look forward to trying this one out.
  15. Just to confirm, you were able to solve it by uncommenting the "RewriteBase /" line in .htaccess?
  16. When using pagination, make sure you set "start=0" on any other non-paginated, DB-selector based calls that include a "limit=n" in them. Otherwise it'll attempt to paginate those too.
  17. This is actually the purpose of $user->language->isDefault(), so that you can differentiate the default site language from all others in one shot, without having a dependency on any specific language. This is largely contextual to a website. If a new user arrives at your website and has not selected a language, what do they get? That's what the default language is about.
  18. Another way to check for homepage is just if the $page->id === 1; because the homepage always has an ID of 1.
  19. You can also do this: $u = $users->add('gonzo'); if($u->id) { $u->firstname = 'Gonzo'; $u->lastname = 'Ipsum'; $u->pass = 'BamBam!'; $u->addRole('guest'); $u->save(); } else { echo "That username is already taken, please choose another"; } The benefit of using $users->add() is that it actually creates and saves the user before you populate it, meaning you can exit out earlier if there is some error. But the main reason is that some fields (like files or images) require the page you are manipulating to have an ID before you can add files. So this saves you from having to think about that. If that's not a consideration, then it doesn't really matter which approach you take.
  20. I personally wouldn't want my view link opening in new tabs/windows, but I can see why some would. I will plan to make it a configuration option on the ProcessPageEdit module. As for how to explain the current behavior to a client, I'm not sure it needs explanation because it works the same as any other form on the web. If you are completing a form and you navigate elsewhere, your form is not still there waiting for you. So if you want to say anything, that's probably the best way to say it: it works the same as any other form you've ever used on the web... as in "don't click to a link until you've finished your form".
  21. The posted code example looks okay to me. But I'm not sure I understand the question… What is the "drop down module"? We'd probably also want to see where $country is coming from and where you are setting $input->whitelist->country. But most importantly, what is the expected output, and what output are you currently getting? Curly brackets only necessary if you've got two "->" in there, meaning, you can do this: echo "$page->title"; but not this echo "$page->image->width"; you'd have to do this: echo "{$page->image->width}";
  22. You should be able to do this during runtime: $page->template->filename = '/path/to/file.php'; or $t = $templates->get('some-template'); $t->filename = '/path/to/file.php'; Note that /path/to/file.php must be a full path and filename relative to the server's file system, but PW won't accept it unless the file ultimately lives somewhere under your web root where PW is installed. Meaning, you can't do this: $t->filename = '/etc/passwd';
  23. ryan

    Freeing the Captcha

    Hopefully you are getting at least some form entries though? There are a couple things in FormBuilder that will likely keep out most spam even if you don't enable any spam prevention measures. You are right that the iframe makes it invisible to most spiders, so that's one of them. The other is that it requires a unique submit "key" for each form submission, and it must match up with the key in the form that was presented, as well as the one saved in the user's session. Most automated spam isn't sophisticated enough to maintain sessions and retain values in hidden fields. They usually just populate every field available with their spam. So it's unusual for spam to get through a FormBuilder form, even if you aren't using any spam prevention measures.
  24. Great site josedigital! I would have never guessed this used the blog profile as a base. Nice work! I think this is pretty common. This is really only an issue if you are selling digital products with instant delivery. In a case like this site, where somebody has to create or ship something, I don't think it's a problem. There's absolutely no benefit to manipulating the values. The paid amounts are almost always in the face of anyone fulfilling orders. If someone is manipulating these things to place an order, it falls under the category of "world's stupidest crimes." They are committing fraud while creating a permanent paper trail and providing personal info like a credit card and/or mailing address.
×
×
  • Create New...