Jump to content

ryan

Administrators
  • Posts

    16,714
  • Joined

  • Last visited

  • Days Won

    1,515

Everything posted by ryan

  1. Manfred62, looks like I broke it in one of this week's commits. I added translation support to uploaded filenames so that you could upload ŖýäŅ-Čřämêŕ.jpg and it would convert to ryan-cramer.jpg rather than ____-______.jpg. It basically runs files through the existing translation engine used by page names (and your settings defined with the InputfieldPageName module). So it was attempting to beautify filenames in the same way as page names, which meant converting things like doubled hyphens to a single replacement character. Obviously that's not compatible with the language JSON file name format, my mistake. I've modified it so that it now allows doubled hyphens, so it should be fixed now on dev. I was also able to duplicate the issue with the Setup and Access page titles/summaries incorrectly displaying in default language, so that should be fixed now as well. Thanks for reporting it.
  2. I'm not sure you can directly compare modx and ProcessWire on load times unless you have them both in original state without any modules installed, except those required by the core. Even then, they may not be directly comparable unless they are accomplishing the same thing and providing the same level of tools at bootstrap. ProcessWire's boot time will be very much affected by how many "autoload" modules and running and how much activity they perform during their initialization process. It will also be affected by your overall quantity of modules, fields and templates. I would assume modx to be the same in that regard (assuming they have some equivalent of autoload modules, fields, templates, etc.). So whichever one is faster may have as much to do with how much stuff you are asking it to load as part of the bootstrap process. We do have a rather extensive API that most systems don't, so we do hand over a lot of ready-to-use tools to your template file and part of our bootstrap, and very likely most systems you'd compare PW to don't have near the scope of tools that we do. But we always want PW to have the best performance possible. In PW a "no api calls" page is not going to make any difference in the time of the bootstrap process, because execution of your code (in your template file) occurs after the bootstrap process. Again, I'd assume modx to be somewhat similar in this regard too. I did measure the time it takes for our bootstrap is a fairly blank state (with regard to modules) and found I was getting about 0.2s (200ms) bootstrap times. Admittedly, this is on a slow computer more than half a decade old, but did have APC enabled (APC is an opcode cache). Then I disabled APC and found they were at least 100ms higher. This is the time it takes ProcessWire to boot and give control to your code. As far as how long it takes after that depends entirely on you and what you are doing with the API. I would guess that in Soma's case, he's got a faster computer than me and perhaps with an opcode cache too. Even though my computer is old and doesn't have much in the way of horsepower, I thought there was some potential to speed up the bootstrap process (there is always room for optimization), so I've gone ahead and applied some optimizations to the dev branch, now available in PW 2.4.5. On the same computer as before, I've got the bootstrap down to 0.08s (80ms) with APC enabled, or 0.15 (150ms) with APC disabled (no opcode cache). This is with a logged-in user, so it's a pretty good performance boost. Is it possible to tell the difference in speed in person? No–we're talking about amounts of times that are beyond our perception (beyond my perception at least). But performance is always a priority in our core. And regardless of whether another platform might boot faster than ours or not, I think most would agree that ProcessWire's performance is always better in the areas where it really counts. In PW 2.4.5 (dev) if you want to measure boot-up times, there is now a "Timers" section in the debug info at the bottom, but debug mode must be enabled to see it. Keep in mind that debug mode takes up quite a bit of resources in its own right, so actual times would likely be less with debug mode off.
  3. Great job Nikola! Fantastic theme! Thanks for making this. I really like how you've taken advantage of Admin Themes being modules with all the configuration options too. For anyone that wants to install this theme, you can do so easily just by logging in, click "Modules" then "New", and paste in "AdminThemeModesta" in the Module Class Name field.
  4. ryan

    Lister

    Think of Lister as a powerful administrative tool, but definitely not a front-end tool. With much power comes much responsibility. You can access any piece of data in the site from ProcessWire selectors (and correspondingly, Lister), so it's not something you want coming from just any user's input. When it comes to ListerPro, that goes even further and lets you modify any piece of data in your site en masse.
  5. The only ones I can think of that you would encounter in the core are template_id or parent_id. Those are used by Page reference fields, PageTable fields and possibly others. If you want to support things beyond that, I'm guessing you'd convert a template_id to a template name, and a parent_id to a page path? You are right that without knowing what the properties mean ahead of time, you'd probably need some interface that externalizes those values to something considered more portable. The thing is I'm not entirely sure that template name or page path would be entirely portable either? It might not always be preferable to the ID, and probably just depends on the situation. You'd instead need some kind of shared GUID that is independent of either system. That may not be realistic, so perhaps just a notice or confirmation during the migration process that certain properties would need to be double checked?
  6. Netcarver, ProcessDiagnostics is beautiful–really enjoying it. I have one suggestion though, which is to either have ProcessDiagnostics install at least one of the diagnostic modules, or to have it display some error if none are installed when you go to Setup > Diagnostics. I tested on a new installation this morning (before I had my coffee) and couldn't figure out why I was getting a blank admin screen when viewing the Diagnostics page. After hunting around in the code trying to figure out why, I eventually slapped myself for forgetting to install any of the related Diagnose modules. But I'm guessing other people might run into the same thing.
  7. Actually you don't need to do anything other than update your GitHub. The modules directory will pick up the new version automatically. However, it keeps a cache from GitHub so it may take up to half a day before it sees the changes. So if you don't want to wait for it you can always edit your module listing manually too.
  8. Nico, tested out here and it works great. Thanks for making this. Just a few minor suggestions: 1. Your 'autoload' selector in getModuleInfo() works well, but might benefit from being more specific, like "template=admin, name=languages". 2. Your hooks to ProcessPageType might also benefit from being more specific, i.e. ProcessLanguages rather than ProcessPageType. 3. Rather than hard-coding the modules directory API key and base URL, you might want to pull it from the ProcessModule module, as it's possible for these things to change over time. Here's how you could grab them: $data = $this->modules->getModuleConfigData('ProcessModule'); $apikey = isset($data['serviceKey']) ? $data['serviceKey'] : 'pw231'; $baseUrl = isset($data['serviceUrl']) ? $data['serviceUrl'] : 'http://modules.processwire.com/export-json/'; Note that above is falling back to hard coded values just in case of an older PW version... not sure that's necessary (I don't remember when these configuration values were added to the core). 4. In your request to the modules directory web service, append "&category=language-pack" in the URL so that your results are limited only to language packs. Don't worry, you didn't miss this before, I just added the category filter option to the service. 5. Your module has downloadFile() and removeDir() methods that duplicate methods already available in the core. Basically, you can save yourself some code here if you want to. See /wire/core/Functions.php. 6. Your module is using ZipArchive. You might find it saves time and code to use the core's built-in wireUnzipFile($file, $destination); method, also in /wire/core/Functions.php 7. In your module's getModuleInfo() method it refers to version 010. Change that to just 10. The leading 0 will make PHP think it's an octal number or something.
  9. MadHatter, thanks for your submission to the modules directory. This seems like a very good and useful module so thanks for making it. In reviewing the module, I had one suggestion/request: Because this is an autoload module, and because your $this->bad array gets populated from your init(), your bad passwords file gets loaded into memory on every request. That's ~73 kb worth of bad passwords that are loaded every time ProcessWire runs, which is a significant amount of memory. Because your bad password list is only needed at certain times (i.e. after InputfieldPassword::processInput), I wanted to suggest moving the population of $this->bad from your init() method to your checkPass() method. Or maybe you don't even need to bother with having a $this->bad array, and could keep it all localized to your checkPass method, as InputfieldPassword::processInput is not likely to be called more than once in a request anyway (i.e. no need to cache it).
  10. PW isn't going to differentiate between wrong password and failed login. If it gave a different message depending on whether the error was with username or password, then the login form could be used as a tool for discovering usernames by dictionary attack (which would be undesirable from a security standpoint). Do your development subdomain and live domains use different /site/config.php files? Check if there are any differences in the $config->userAuthSalt line. Are there any differences in the PHP versions? While in your /site/config.php file check that you have a $config->httpHosts = array('domain.com', 'dev.domain.com', 'www.domain.com'); line in there (accounting for all possible hostnames). This isn't involved with passwords, but it can cause issues that might potentially have that appearance if not configured properly.
  11. HTTP hosts, sessions, cookies don't come into play with passwords. Some other factor must be at play during that migration. Of course, a change in hostname will kill active sessions, since the session is tied to the HTTP host. But that's no different than if you just logged out. What can affect passwords is the PHP version and what capabilities it has with regards to encryption support. If you are running PHP 5.3.8 or newer (our current minimum requirement) then it won't be a factor unless you are moving to a PHP installation where the administrator has disabled some of PHP's encryption functions (which would be unusual and rather bad from a security standpoint). I kind of doubt that any of the above are it. What is more likely is a change to the $config->userAuthSalt (which appears at the bottom of your /site/config.php file). That particular value is generated randomly when you first install ProcessWire. It is forever tied to the passwords as a secondary salt. It's not technically necessary to have it, and passwords are already blowfish'd, but I've always felt better having one part of the salt disconnected from the database itself. If that salt changes or is lost, then all the passwords are forever broken. Is it possible you changed out the /site/config.php or even accidentally modified the value of userAuthSalt?
  12. Just to clarify, all the recent messages in this thread have to do with the PageTable field, not the ProFields Table field. So the subject of this thread seems to have changed. They are completely different modules, and PageTable is part of the ProcessWire core (on the dev branch), not a commercial module. My responses below have to do with this core PageTable field since that's what all of the questions above are about. For people wondering about the ProFields Table field, please ignore this message. That behavior is intentional. It means you can have multiple PageTable fields on the same page storing their items as children of the page. You might even be using a PageTable field specifically for the purpose of managing children. Though perhaps an option to have them to default to a hidden status might be useful here. In your template page list settings (under advanced) you might also want to specify some other property from your PageTable pages to show in the page list, so that you can easily differentiate them from other children (if any) in the Page List. For instance, you might tell it to display the template name in addition to the page title. For situations where storing them as children is not what you want, then you'd want to specify your own parent. In fact, most of the time when I use PageTable, I specify my own parent where I want them to live, usually off in /tools/my-field-name/ or something like that. We don't want to prevent that because that would mean the PageTable now owns the children of that page and you couldn't use them for anything else, nor could you have multiple different PageTable fields storing their items as children. If you are in a situation where confusion is resulting from letting PageTable store items as children of the page, then that would be a situation where you'd want to specify what parent they should go to instead. In fact, I think that using PageTable with children is really for specific uses, and using PageTable with a specified parent is the more common use case. Try clearing your cache and hitting reload a couple of times in the browser. It looks like something isn't loaded. I'm honestly surprised you aren't seeing a JS error because it definitely has the appearance of that. Beyond the above, try switching your color theme back to "Classic" (just in case I missed something in the last CSS update). You can do this from Modules > Core > Admin Theme. If it's still not working right, I would try updating your core again just in case some files didn't make it through when you last updated it. Please let me know what you find.
  13. Flavy, I wouldn't worry too much about quantity of queries. Instead, focus on the end results and how fast it performs. Quantity of queries means very little as you can have a 100 well optimized and/or simple queries that execute faster than a single complex one. So counting queries is more than often a waste of time, and trying to combine queries can even slow things down. The way that ProcessWire works is that it loads data on demand, as it is requested, using simple and well optimized and indexed queries that are very fast. That is, unless you check the box for "autojoin" in your field advanced settings. When checked, it will join that field's data with the original page query. For instance, we have the "title" field set to autojoin by default, since this is one field that is most likely to be accessed on any given page object. However, whether or not autojoin speeds up anything is debatable, so I would use it sparingly. It has potential to speed things up in some cases, but at the cost of memory, and cost of loading data unnecessarily. As a result, we only recommend it for fields that will always be accessed on every instance of a page. Beyond the obvious "title", examples might include a date or summary field used when outputting lists throughout a site. For the most part, I don't use the autojoin option at all anymore except for "title" fields because there is rarely a measurable benefit, but there is always a measurable drawback (loading stuff in memory that may or may not be used). You might also want to look at the "Cache" Fieldtype, which is included in the core. It's something that people rarely use, but it is directly applicable to your question. It caches all of your fields for a given page (or at least those you select) into one. It's more often used to combine several text fields together for searching purposes, but it can also be used to keep all your page data together in one chunk (and correspondingly, 1 query). Again, it may or may not result in faster performance in the end, but it's another tool worth knowing about and worth experimenting with. Other tools I recommend considering are MarkupCache (core module) and Template cache (a feature in any template settings). Or for the best performance, we also have ProCache, which makes your site perform as quickly as static HTML files. Most PW sites don't need much in the way of caching, but if you find you need it or want it, you've got some great options here. I agree with Antti that 100 fields will not be a problem. Many of us here regularly deal with more than that. But it also is good to think of fields as a finite resource and something that you want to conserve. While there is no technical limit on quantity of fields that you can have, it's possible for overhead to increase as the number of fields do. This isn't about page loading per se, but about overall system overhead and memory required to manage lots of fields at once. The ProFields package is specifically aimed at reducing the quantity of fields necessary to accommodate a site's data needs. Depending on what those needs are, it has the potential to drastically reduce the number of fields in your system. As a result, I think it makes a lot of sense for the needs you are talking about. You should also look into PageTable (on the dev branch) as a better option to repeaters.
  14. Currency Conversion for ProcessWire This module is designed for performing currency conversions among ~165 world currencies. It uses OpenExchangeRates.org (or compatible) for data so that currency exchange rates are always up-to-date. It provides various API functions that you can use to convert from one currency to another. This is especially handy for generating rate tables in multiple currencies or giving users of your site the option to see prices in their currency. How to install How to use API documentation Modules directory page GitHub Page Download ZIP Live Example Requires ProcessWire 2.4.0 or newer. To use the quick-installer from your modules screen, paste in ServiceCurrencyConversion. Basic Example $cc = $modules->get('ServiceCurrencyConversion'); $dollars = 100; // amount of currency we want to convert $euros = $cc->convert('USD', 'EUR', $dollars); echo "<p>$dollars US Dollars equals $euros Euros</p>"; For a live example of a currency conversion tool built with this module see the included convert.php file and test it out here.
  15. Individual images may not have a dedicated ID, but the page ID they belong to + the filename is always unique, so that's all you'd need. Of course, you could always manage pages-to-images on a 1-to-1 basis, but if you wanted to have a page with multiple images on it, each with their own URL, you could also enable URL segments for your template and output them like this: $filename = $input->urlSegmentStr; $image = $filename ? $page->images->get($filename) : null; if($image && $image instanceof Pageimage) { // output your image content echo "<img src='$image->url' alt='$image->description' />"; echo "<p>$image->description</p>"; } else { // output your regular content echo "<h1>$page->title</h1>$page->body"; } With regard to a likes system, is what you are looking for something similar to the likes system you see in our sites directory or the recommendations system in our modules directory (both are actually the same system). If so I can pass along a little more info on how that was done.
  16. I still use your testing library every single day that I code PW. It covers all the most important scenarios, so isn't out of date at all. But I will plan to update the tests for the new selector options. It is feasible to support with repeaters, and if there's demand for it I'll add it. PageTable supports them already just because PageTable delegates huge amounts of its functionality to FieldtypePage, including the implementation where the @ grouping option is supported. File or Image fields. File fields can have descriptions just like image fields can.
  17. ryan

    What is "Reiska"

    I don't know for sure what Reiska means either, but @apeisa told me that was apparently my Finnish name and that it means something along the lines of handyman. I had a member-title spot open, so I put it there. But if it's translating anywhere as "god of all heavens" or something like that, then I need to change it. I'm okay with being a handyman or somebody that fixes things, but need to change it reads as something egotistical.
  18. It's more efficient to do it in one find() operation, using the new options available. When using two separate find operations, all the pages from the first find() operation have to be loaded. When you do it in one find(), then those pages don't have to be loaded. So it can actually be a whole lot more efficient, especially if dealing with larger scales. There is still some room for optimization so I'll be working on that, but regardless they should be a lot more efficient than multiple find operations. Another good reason to use OR-groups (and sub-selectors, depending on the case) would be for pagination. You really can't achieve paginated results very easily if splitting into multiple finds.
  19. Continuing from my previous post in this thread about some selector enhancements available on the dev branch, we've got a couple more advanced options for use in selectors in case anyone is interested: OR-groups These let you specify multiple expressions and only one of them has to match in order for the selector to match. It's a way of saying "either this has to match OR that has to match". This is useful because selectors always assumed AND – meaning everything has to match. While you have always been able to use the pipe "|" to specify ORs for fields or values or both, the scope of it was just that field=value statement only. Now we have something new called OR-groups. These let you create multiple selector groups and only one of them has to match. You can specify OR-groups by surrounding selectors in parenthesis. An example demonstrates it best. Lets say that we wanted to find all "product" pages that were in stock, and either in a featured date range, or had a highlighted checkbox checked. Previously we would do like this with two separate find operations: $items = $pages->find("template=product, stock>0, featured_from<=today, featured_to>=today"); $items->add($pages->find("template=product, stock>0, highlighted=1")); Now we can do it in one find operation: $items = $pages->find("template=product, stock>0, (featured_from<=today, featured_to>=today), (highlighted=1)"); Above are two selectors surrounded in parenthesis. Only one of them has to match. You can specify as many of them as you want. This type of OR expression is something you couldn't previously do with selectors. Think of the parenthesis as a way of saying "this is optional". But of course, at least one of your parenthesized selectors has to match in order for the full selector to match. I'm guessing the above usage probably covers 99% of the situations where you might need it. But lets say that you want to have different combinations of OR expressions. You can create named groups that OR with each-other by specifying: foo=(selector1), bar=(selector2), foo=(selector3), bar=(selector4) In the above you'd replace "foo" and "bar" with names of your choice. And you'd replace the "selector" with any selector strings. Those foo/bar names aren't referring to fields, instead they are just named groups that you can name however you want. In that selector, at least one of the "foo" named selectors would have to match, and at least one of the "bar" named selectors would have to match. If you didn't use the foo/bar named groups here (but still used the parenthesis), then only one of the 4 selectors would be required to match. Sub-selectors Some of you are already familiar with these because it was committed to the dev branch a couple weeks ago (and I think may have been outlined elsewhere in the forums). Sub-selectors let you put a selector within a selector, enabling you to perform more complex matches that used to require you to use separate API calls. These can be used on the 'id' property of any field that maps to a page. The 'id' property is assumed when referring to a page reference or a parent, so it's not necessary to specify it unless you want to, i.e. "field" and "field.id" mean the same thing in this case. Sub-selectors are specified between [square brackets]. For example, lets say we are matching products and our product template has a "company" page field. Each company also has it's own page field where all the company locations are identified. Lets say we want to find all products that are made by a company that has more than 5 locations and at least one of those locations has "Finland" in the title. Previously we would have had to do it like this: $companies = $pages->find("template=company, locations>5, locations.title%=Finland"); $items = $pages->find("template=product, company=$companies"); That's easy enough. But now it's even simpler, as you can do it in one operation: $items = $pages->find("template=product, company=[locations>5, locations.title%=Finland]"); When you've got a "field=[value]" selector, any properties you refer to in "[value]" assume the "field", so "locations" above is referring to a property of the "company" field.
  20. Feasibly it's possible, but it's not desirable. Making wire('var') aware of context involves pre-compiling the template files to replace wire('var') with wire($this, 'var'). So it's something we do to provide backwards compatibility in template files. We won't be providing that backwards compatibility outside of template files, so people will have to use $this->var, $this->wire('var') or wire($this, 'var'); elsewhere. Also, a Static::syntax implies dealing with a framework that only has one context, which gives the appearance of a weakness that isn't there, something I think we'd want to avoid. While I'd really like to limit statics in ProcessWire as much as possible (just because they are more than often a bad programming practice), that syntax is perfectly fine for static functions where context doesn't matter or where you are passing the context into it. For example, $sanitizer functions would not need to have different behavior in different contexts. I've even seen some frameworks that do use statics for sanitization functions as well. In the end though, IMO they would still be better served by providing the same functions non-statically. The plan is that when you do this... $main = new ProcessWire('/site/'); $intranet = new ProcessWire('/site-intranet/'); ...everything in each of those two instances will be unique to those instances and whatever site files are stored in /site/ or /site-intranet/. That means that when a module is initialized, it is only initialized for the instance (whether main or intranet). When a module refers to $this->var, it's referring to API variables that are part of its instance only. This enables you to have multiple sites talking to each other. Currently this isn't possible precisely because PW uses statics for API variables behind the scenes. But the fact that we've kept that behind the scenes is a good thing because that means it doesn't matter how our API variables are stored. We can switch them to a stronger storage mechanism that would be tied to an instance. This is one reason why I deprecated the Wire::getFuel() syntax (that appeared in early versions of PW2) early-on... though you might still see it appear in a few core spots, which will need to be changed. But we've really tried to keep the public API clear of static calls so that the API would not have to change as PW continues to grow as a framework.
  21. You could install it in /wire/modules/ rather than /site/modules/. However, I don't recommend doing that because it'll get overwritten every time you upgrade the core, which would be a bigger problem than having multiple copies of it. Use symbolic links instead (for /site/modules/ProCache/) and you'll only have to keep one copy of the ProCache files.
  22. As a basic test case, you could add this to your /site/templates/admin.php wire()->addHookAfter('InputfieldPassword::processInput', function($event) { $inputfield = $event->object; $password = $inputfield->attr('value'); $bad = array('test', 'abc', '123', 'password', 'unicorn'); if(in_array($password, $bad)) { $inputfield->error("That's not good enough of a password, try again"); $inputfield->attr('value', ''); } });
  23. @kongondo the functionality was added a little while back and is already in the stable 2.4.0. See these four hooks in Pages.php.
  24. Around PW 3.0, I'm looking to make PW multi-instance compatible so that you could have multiple ProcessWire instances (each connected to separate databases) running from the same PHP code. This opens a huge amount of flexibility. But it also means that any kind of static references will have to disappear because function calls like Wire::getFuel('var') and wire('var') make the assumption that there is only one instance of ProcessWire running. This is one of the bad things about static calls in general. When that time comes, we will be able to apply contexts to our template files so that calls like wire('var') still work. But the reality is that non-static calls like $this->wire('var'), $this->var, and $var are technically superior when it comes to a multi-instance environment. So my opinion would be that it's not good to introduce new static calling methods when they may soon be obsolete.
  25. There's a security problem here. You are placing an unsanitized variable into a selector. Think of that like SQL query injection, even if it's not quite that dangerous. But you want to avoid any instances where user input could start expanding your selector string. So always sanitize user input before using it. In this case, if you know that $min is always going to be an integer or a float, then make it an integer or a float: $min = (int) $input->get->min; // if integer $min = (float) $input->get->min; // if float If you are dealing with some type of string, then at minimum sanitize with $sanitizer->selectorValue(): $value = $sanitizer->selectorValue($input->get->value); Do all of this sanitization before placement in a selector. Lastly, it doesn't matter whether you use $_GET or $input->get (or $_POST or $input->post), but I prefer to use $input->get or $input->post because they remove the issue of PHP's magic quotes setting, which may cause unexpected slashes to appear in your input, depending on the server settings.
×
×
  • Create New...