Leaderboard
Popular Content
Showing content with the highest reputation on 12/21/2014 in all areas
-
The links are of mixed usefulness actually - the majority of the Wordpress ones are for plugins so not the fault of the Wordpress core or a useful comment on it's suitability as a system - just a highlight of buggy third-party modules (same with Joomla too). It would be better split out into core bugs (far fewer) and then alphabetic by plugin really so you can see it more clearly. They're actually pretty skewed results as Wordpress clearly has more plugins than any other system (1,425 in their plugin directory just for the search term "gallery") so has the most security issues listed as a result. So I don't think it's fair to blame those numbers on the systems in question. Feel free to blame it on not assessing the plugins/modules and use it as a case when telling customers "yes, you could use Wordpress, but are you sure the plugins you are going to use are safe?". It's a bit of a minefield to say the least. The reason zero security vulnerabilities have been reported in ProcessWire is because, at the moment, I am not aware of anyone finding any (anyone else?). There is nothing that ryan etc are hiding - it is just incredibly stable and the way the API abstracts things away from SQL queries removes one of the biggest pitfalls - no chance of SQL injections! The only things I have seen "fixed" over the years are a few bugs (not security related) and areas where performance has be increased. I would definitely agree that anyone finding a vulnerability should report it - probably via the contact page is fine - so that there is time to fix it and issue a patch. I'm sure we would welcome that as well as them appearing on Secunia, but I don't think there are zero reported security issues on Secunia because nobody is bothering to report them - simply that nobody has found any yet to my knowledge. I am equally happy if someone finds a security issue or two and reports it in a responsible manner, but I'm being a "glass half full" guy rather than assuming a lack of transparency. Could it be that ProcessWire is just incredibly well-written? I'd like to think so, but I am sure time will tell either way Certainly if the quality of modules continues and they go through a proper approval process then we can avoid some of those high numbers on the links above, but we will never get to those high numbers I think - I can't imagine a time when we would ever have 1,425 gallery modules even if ProcessWire grew to be more popular than Wordpress - there really must only be so many ways you can put together a gallery so there will never be as many modules (of any type) and therefore no real chance of having that high number of vulnerabilities. At least I hope not6 points
-
In the admin we have an option to set a sorting for children using one field only. I have a problem with children getting sorted randomly when using a date field that is the same for multiple children. Usually we would sort by date and by ID or title, but we are only allowed to specify one field at a time. The problem with this is that once you edit one of those children, the sorting is randomly changed (actually everytime you edit a children) That's not really nice and very confusing. I had to use a dirty hook to change the children sorting one parent manually. $this->addHookBefore("ProcessPageList::find", $this, "sortingChildren"); public function sortingChildren(HookEvent $event){ $sel = $event->arguments("selectorString"); $page = $event->arguments("page"); if($page->template == "news-category"){ $event->setArgument("selectorString", $sel . ",sort=-datetime, sort=-id"); } } Maybe there's already a way I don't know or a module? But then I think this should be in core of course and not a module. Thanks.3 points
-
Build my first PW website...., and not my last. Like PW a lot. It is fun to work with and sometimes a challenge. Spent, more than once, some ours fiddling on code issues, but real proud when I got it to work. Could not have done it without the feedback of the members from this community, thank you! Modules I used: -Email Obfuscation -Form Builder -SEO -Blog -Google Analytics -Protected Mode -Wire Mail SMTP Other: -Bootstrap -Animate -WOW -Unslider Website: http://www.tweemansterk.nl3 points
-
Wow, thank you so much everyone. Thank you especially @horst and @ivan gretsky. I found the video really helpful for understanding what the page field does. And @horst your detailed instructions are just what I need as a beginner. I have followed your steps @horst, and all went well until I added the quote_category field to the quotes template. The only difference between what I have done, and what you have suggested in steps 1-3 is that I have named the parent folder for the categories as 'quote_categories'. Next problem... I have created a field called 'quote_category' and assigned it a type of 'page'. When I assign it an Input Field Type of 'AsmSelect', and choose 'quote_categories' as the Parent of selectable pages, I have a problem. When entering text into my quotes template, for the 'quote_category' field I get a drop down list that only contains the text '1051' (see screenshot here). UPDATE: Resolved I think '1051' was showing up in the dropdown list because I had not published my quote_categories child pages. When I published them, they showed up in the drop down list. Other beginners take note! I will keep you updated on how I go with this random quote display exercise. Stay tuned!3 points
-
2 points
-
@reems This sounds similar to a issue I had recently https://processwire.com/talk/topic/8345-deleting-large-number-of-images-silently-fails/ In my case increasing max_input_vars in my php.ini solved the problem.2 points
-
@z Thanks for getting back and glad you found the issue. I think you'll run into many problem with 32mb real quick so I don't think setting memory limit in modules is a good way as it belong to server configuration. ----------- Note about an update to 2.1.6 - Fixed issue with an unexpected "\n" char in a summary of a newly added module that caused and error with jQueryDataTables parsing the json. So I'm sure many will run into this issue once they hit refresh and haven't updated to 2.1.6 yet. But see and make an update of ModulesManager you'd need to hit refresh. - So not sure how this will play out. Damn "\n"! In case just manually update or use the core module manager.2 points
-
1) I think using pages will be the best decision. 2) I would propose to use page field to relate quotes to categories. 3) You can use this to get a random page.2 points
-
FieldtypeMatrix and InputfieldMatrix Modules Directory: http://modules.processwire.com/modules/fieldtype-matrix/ GitHub: https://github.com/kongondo/FieldtypeMatrix The module Matrix enables you to save data from a 2D-Matrix table. The rows and columns of the matrix table are made up of pages retrieved via a ProcessWire selector or via a page field selection of parent pages. The matrix values are made up of the data input in the matrix cells, i.e. the 'intersection of rows and columns'. Example Usage You have Products whose prices vary depending on colour, size, material, etc. Using the Fieldtype, you can create a table with rows made up of colours and columns made up of sizes the combination of each making up their respective values (in this case price). So rather than creating multiple text fields to do the following: Colour Size Price Red Small £10 Red Medium £20 Red Large £30 Red X-large £35 Green Small £9 Green Medium £15 Etc... You can instead have the following in one field: Small Medium Large X-Large Red £10 £20 £30 £35 Green £9 £15 Blue Etc... Yellow Purple If you set a selector in the Field's settings, to retrieve pages to build your matrix's rows and columns, it follows that all pages using the template the Fieldtype is attached to will have identical rows and columns. In some cases, this could be the intention. For instance, you might have 'Car' pages, e.g. Audi, Volvo, Ford, Citroen, Mazda, BWM, etc., each of which uses a 'Cars' template that has a single FiedltypeMatrix called 'car_attributes'. If you set a selector to build the Fieldtype's rows and columns, your users can easily compare the cars based on a combination of different values. The following matrix table best illustrates this: Type Engine Size Fuel Efficiency Carbon Emissions Warranty Road Tax Price 1994 Audi brand 1 values, etc. 2000 Audi brand 2 2006 Audi brand 3 2012 Audi brand 4 Each of your car pages would have similar matrices. This allows you to make easy but powerful queries. Such a setup allows you to compare within and across car brands. Say you wanted to find out which car(s) offered the best value for money given certain parameters such as warranty, emissions etc. You can easily make such comparisons (see code below). You can also compare within one car type, e.g. which brand of BMWs does best in what area...The possibilities are endless. In the database, Rows and column pages data are stored as their respective page->id. Matrix-values store any data (varchar(255)). If instead you wanted a template's pages to each have a matrix built of different rows and columns, you would have to name a Multiple Page Field (attached to the same template as the as your matrix field) in the matrix field's settings. When editing those pages, your matrix table's rows and columns will be built using the published children pages of the 2 pages you select in the Multiple page field.. The module allows the creation of matrix tables of any sizes (rows x columns). The rows and columns dynamically grow/shrink depending on the addition of row/column pages that match what you set in the matrix field's settings (see its 'Details Tab'). Please note that, if such pages are deleted/trashed/hidden/unpublished, their data (and presence) in the matrix are also deleted. Entering values in the matrix You have three choices: Manually entry Uploading a comma delimited (CSV) file. This can be delimited by other characters (tab, pipe, etc); not just commas Copy-pasting CSV values. (Tip: you can copy paste directly from an Excel spreadsheet. Such values will be 'tab-delimited'). In addition, if your server supports it, in the field's settings, you can enable the use of MySQL's fast LOAD DATA INFILE to read and save your submitted CSV values. Note that for large tables, you may have to increase your PHP's max_input_vars from the default 1000 otherwise PHP will timeout/return an error and your values will not be saved. I have successfully tested the module with up to ~3000+ values (10x350 table), the Fieldtype is not really optimised (nor was it intended) to handle mega large matrix tables. For such, you might want to consider other strategies. Install Install as any other module. API + Output A typical output case for this module would work like this: The matrix's rows, columns and values are subfields of your matrix's field. So, if you created a field called 'products' of the type FieldtypeMatrix, you can access as: product.row, product.column and product.value respectively foreach($page->matrix as $m) { echo " <p> Colour: $m->row<br /> Size: $m->column<br /> Price: $m->value </p> "; } Of if you want to output a matrix table in the frontend: //create array to build matrix $products = array(); foreach($page->matrix as $m) $products[$m->row][$m->column] = $m->value; $tbody ='';//matrix rows $thcols = '';//matrix table column headers $i = 0;//set counter not to output extraneous column label headers $c = true;//set odd/even rows class foreach ($products as $row => $cols) { //matrix table row headers (first column) $rowHeader = $pages->get($row)->title; $tbody .= "<tr" . (($c = !$c) ? " class='even' " : '') . "><td class='MatrixRowHeader'>" . $rowHeader . "</td>"; $count = count($cols);//help to stop output of extra/duplicate column headers foreach ($cols as $col => $value) { //matrix table column headers $columnHeader = $pages->get($col)->title; //avoid outputting extra duplicate columns if ($i < $count) $thcols .= "<th class='MatrixColumnHeader'>" . $columnHeader . "</th>"; //output matrix values $currency = $value > 0 ? '£' : ''; $tbody .= "<td>" . $currency . $value . "</td>"; $i++; } $tbody .= "</tr>"; } //final matrix table for output $tableOut = "<table class='Matrix'> <thead> <tr class=''> <th></th> $thcols </tr> </thead> <tbody> $tbody </tbody> </table>"; echo $tableOut; The module provides a default rendering capability as well, so that you can also do this (below) and get a similar result as the first example above (without the captions). echo $page->matrix; Or this foreach($page->matrix as $m) { echo $m; } Finding matrix items The fieldtype includes indexed row, column and value fields. This enables you to find matrix items by either row types (e.g. colours) or columns (e.g. sizes) or their values (e.g. price) or a combination of some/all of these. For instance: //find all pages that have a matrix value of less than 1000 $results = $pages->find("products.value<1000"); //find some results in the matrix (called products) of this page $results = $page->products->find("column=$country, value=Singapore");//or $page->products->find("column=$age, value>=25"); //$country and $age would be IDs of two of your column pages Other more complex queries are possible, e.g. find all products that are either red or purple in colour, come in x-large size and are priced less than $50. Credits @Ryan on whose Fieldtype/InptufieldEvents this is largely based @charger and @sakkoulas for their matrix ideas Screens Field Details Tab Inputfield Larger matrix table Example output1 point
-
I recently created an ecommerce website, iBuildMacs, that I built with ProcessWire. Given that there's been quite a bit activity on combining ecommerce with ProcessWire, I feel many people would be interested in the approach I took. Feel free to visit it at: http://ibuildmacs.com/ The requirements for this site were: a computer configurator, much like the Apple website; example product page here cart checkout payment methods: paypal or check/cash shipping methods: the cost of shipping is based on a fixed cost that is related to the country being shipped. no live quotes The requirements did NOT include: tax rules inventory management coupons, gift certificates different product types: simple products, variable products, digital/downloadable products, etc. user accounts, address management a fancy ajax driven checkout So, I had a bit of flexibility for this site given the specific feature set. I then thought about how I wanted to develop the site. The options I considered included: WooCommerce: I've built several intricate websites with WooCommerce, the most recent being caviar.com. It was good fit that website, but for iBuildMacs, which has less requirements and a very unique product configurator, which WooCommerce could do but with a tremendous amount of overrides and working backward, I decided this wouldn't but the right fit. Plus, I'm trying to become as WordPress-free as possible. FoxyCart: A ProcessWire favorite, however I wanted to challenge myself a little bit with this site, and also keep things under one roof. Magento, Shopify, (insert some specific heavy or cloud-based ecommerce system you like): No. Overkill and making a product configurator would be a pain. After considering my options, I felt just rolling it entirely with ProcessWire and programming the catalog, payment methods, shipping methods and checkout tailored to the site's specific needs was the way to go. This would definitely reduce the time and headache needed in bending anyone of the above systems I mentioned to behave exactly the way I wanted it to. Products This was one of the complicated parts of the website, but ProcessWire, with its infintely flexible custom fields, made this a breeze. I have a product template (product.php). It has some general fields like Title, Body, Image and Base Price. It also has a PageTable field called Features. These features are child pages of the product and use feature template (feature.php), so the Features PageTable field just grabs its data from there. Then, the feature template has some general fields like Title, Body, Image and PageTable field called Feature Options. These feature options are child pages of the feature template using the feature option template (feature_option.php). So, what I ended up having is a 3 level deep structure, with two nested PageTable fields. Here's a video of what it looks like, which is quite slick is very easy to manage: https://vid.me/kjDW Cart When a user adds a configured product to their cart, it must be stored somehow and I thought of a variety of ways to do this. Ultimately, I decided that cart data is handled as a page (using the order.php template) undernearth /orders/. This order.php template has a page name that is based on the session id of the user, so it'll remain unique and not cause a conflict with other people's carts (as well as obscure from people trying to guess it's url, which is used for the order confirmation page). One of the fields in this order.php template is called "products_ordered", which utilizes the Table fieldtype (a Profields table). Video: https://vid.me/MIRl Checkout The checkout is a straight forward form with the basic questions. However, the shipping section is where it gets tricky. The requirements for this site were that each computer has a fixed shipping price depending on the method being used to ship. The shipping methods available to a customer are dependent on their country. I think WooCommerce could manage rules like that, but directly coding it wasn't that difficult. I create an array that stored the 2 payment methods, and another array that stored the 6 total shipping methods. I also have an array for all the countries. I then wrote some JavaScript that managed the relationships between the country chosen and the shipping methods available for the chosen country. When choosing a method, it will update the Shipping cost line item on the car to the right. Just basic JavaScript going on here. All nice and on one page. When the submit button is pressed, it will run through some logic and validate all the data and save it to the same page that stored the cart data. An order confirmation email is sent to the customer, and one is also sent to the admin (SwiftMailer). If Check/Cash was chosen, the user is then simply forwarded to the order confirmation page, which is at /orders/whatever-their-page-name-was-saved-as/. The email they are sent also has a link referencing this page. If PayPal was chosen, a URI is built and the user is taken to PayPal complete payment with PayPal Payments Standard using the Cart Upload command. Documentation here. After they complete Payment on PayPal, they are then taken to the order confirmation page as described previously. Video: https://vid.me/hwfB I will eventually be using ListerPro for a nicer admin orders list display and build a few custom actions to allow administrators to quickly send general emails from the system (like, when the order is shipped). Modules Used Admin Template Columns: http://modules.processwire.com/modules/admin-template-columns/ Markup Simple Navigation: http://modules.processwire.com/modules/markup-simple-navigation/ Maintenance Mode: http://modules.processwire.com/modules/maintenance-mode/ Batcher: http://modules.processwire.com/modules/process-batcher/ Form Builder (for the contact form only): https://processwire.com/talk/store/category/2-form-builder/ Swift Mailer: http://modules.processwire.com/modules/wire-mail-swift-mailer/ PageTable field type ProFields Table: https://processwire.com/talk/store/category/7-profields/ ListerPro (eventually): https://processwire.com/talk/store/category/9-listerpro/ Enjoy!1 point
-
This should be very easy to add. Sorry I don't have time in the next few days and so it will probably have to wait till the new year, but if you are in a hurry, take a look at: http://flourishlib.com/docs/fMailbox That shows what you need to add: "received" (date) and "from". If you decide to add this support before I get a chance to look into, please send me a PR It seems like going forward, this module needs to be further configurable so you can decide what fields you want stored and which PW fields you want them added to.1 point
-
1 point
-
And some more minor changes: I switched to PHP_EOL instead of \n and \n\r, which should solve the double line break issue. And I added a option, to add a whitespace at the beginning if automatically inserted. (will publish it in 10min)1 point
-
Version 0.6.0: Big feature: Google suggestion autocomplete Google preview updates while you type Custom contents only get sanitized now Bugfixes @NorbertH: This is not an image field because you can't have an image field in the modules config settings page. And I think this is good enough for now. Maybe I change my mind later on @toothpaste: Why no line breaks?1 point
-
$numComments = $page->blog_comments->count(); @Peter beat me to it...https://processwire.com/talk/topic/7403-module-blog/?p=83118 If anybody else wants more examples let me know...1 point
-
Hi nickie, check these posts: https://processwire.com/talk/topic/17-functionsmethods-to-access-the-db/ https://processwire.com/talk/topic/669-using-a-secondary-database/1 point
-
Not in this particular case, but there are times when a str_replace would suffice. In this case it would be a bit hacky .... Btw, is a 'summary field' like this a common feature of Blogs? Anyway, your question got me thinking, so thanks for asking ....Given your example, there's maybe 3 options to enable you to inject your custom fields inside Blog Markup (i.e. modify the markup server-side). Option 1. Add an post_extra_fields => array() I could add an 'array option' in renderPosts() 3rd argument, i.e. $options for specifying any extra fields (that return strings) that a user might want to inject in their markup (e.g. your post_summary field), i.e. a post_extra_fields => array() $options = array( 'post_small_image' => 3, 'post_small_image_width' => 250, 'post_comments_label'=>'', 'post_extra_fields' => array('post_summary' => 1, 'post_teaser' => 4, 'post_other_field' => 3); ); The numbers in the values inside 'post_extra_fields' (e.g. 1 in 'post_summary') refer to the position (see illustration below) where you want that extra field to appear within the Blog Post Option 2. Add other methods to output various parts of Blog Posts In this option, those who wish to use renderPosts() can do so but those who want finer control can use these other methods, i.e. renderPostTitle() renderPosByline() renderPostBody() renderPostCategories() renderPostTags() .....but hold it right there. What is wrong with this picture? renderPostTitle()! Why create a method to do what ProcessWire already does ($page->title) and does well!? Option #2 (and probably the first one too) is dead in the water and I'll show you why in option #3 below. Option 3. Use both native ProcessWire methods/properties and MarkupBlog methods as applicable I will need to put this in the Blog Docs as well. What I should have been clear about in the Blog Docs is that you do not have to use renderPosts() to output the main content of your Blog Post (i.e., post title, post body, etc). You can, if it suits your needs, use native PW methods/properties, especially if you want full control over your Posts structure and Markup. Nothing stops you from combining these with MarkupBlog methods. For instance, you can use MarkupBlog to render your Blog's tags, categories, authors, archives, etc but use ProcessWire methods/properties to render your Blog Post including adding content from any other extra fields you have anywhere on your site. So instead of: $content = $blog->renderPosts($page, '', $options) . $blog->postAuthor() . $blog->renderComments($page->blog_comments) . $blog->renderNextPrevPosts($page);//with post author in your blog-post.php...you can have: $content = $body . $blog->postAuthor() . $blog->renderComments($page->blog_comments) . $blog->renderNextPrevPosts($page);//with post author ..where $body is a variable holding your custom content (blog_body, post_summary, $page->title, etc). I will write a full example in a post below. So, back to the original question. How do we inject extra content or have full control over our Blog Post Markup if we do not want to or cannot use str_replace, etc.? Use option #3. Unless convinced otherwise, this is the option I will be recommending (hence, for now at least, will not be adding option #1 to renderPosts()). OK, let me finish writing the example option #3...1 point
-
Hi @kathep, welcome to PW and the forums. As with the most things here, there are no "right way" to do it. There are a few more or less equal but different solutions possible. What come into my mind are three variations: a) simply going with single pages b) going with repeaters c) going with Profields Pagetable I would go with single pages: 1) build a page called tools or something that only serves as parent for stuff that is not used to be displayed directly to the forntend. Set the page to hidden. 2) Build a template called category, it only needs a title field I think create a page under tools called categories that should serve as parent for your categories build child pages under categories that have the template category and the title are the names of your categories you need 3) Build a template called quotes, build the fields you need to be on a quotes page: quote_text = textarea quote_author = text quote_category = page, best is to use it with ASM select!, the source for it is the category parent! etc and assign them to the template Build a page under tools called quotes as parent for all single quote pages create your quote pages there (if you have to many for a manually creation, there are also automated import solutions available) If you have all setup you can get the quotes from every where in PW with a selector like this // get all quote pages $quotes = $pages->get("/tools/quotes/")->children(); // get all quote pages of a specific category $quotes = $pages->get("/tools/quotes/")->find("quote_category.title=category1"); // get all quote pages of a few specific categories $quotes = $pages->get("/tools/quotes/")->find("quote_category.title=category1|category2|category3"); // to get only one random out of those collections you call ->getRandom() at the end $quote = $pages->get("/tools/quotes/")->find("quote_category.title=category1|category2|category3")->getRandom(); If you get stuck at some point with this, come back and tell us.1 point
-
So I think I'm going to change MarkupSEO back to creating "real" fields. This will allow multilanguage and has some other benefits as this module is used by a lot of you lately.1 point
-
I think at the moment ryan approves all modules before they appear in the list so I assume he is looking at the code before approving them. The problem is, as a play on what Joss says above, you can do just as much damage without modules on your own. You can open up security vulnerabilities in any CMS with a little effort (I believe both MODx and WP allow you to write pure PHP in templates/snippets as well as PW of course), so even leaving modules aside it's possible to create your own issues in very few lines of code and be totally oblivious to the dangers. My point is, modules or not, a lack of knowledge is the enemy here. Not everyone has the knowledge necessary (myself included) to understand the more complex modules out there so the recommendation that I would love to give of "don't use a module if you've not investigated its code" doesn't even work for me I guess the best thing moving forward is to have a few more people checking out the modules submitted to the Modules page and recommend that nobody downloads modules that haven't been posted there. That might seem harsh as I know there are many good modules only on Github, but if nothing else it will encourage people to submit their modules to the directory - let's face it, it doesn't take much time at all.1 point
-
I love the Telecrapper. Some guy hooked his landline up to a computer which could recognise incoming cold calls by their number. His computer would then kick in with a series of random conversations he'd pre-recorded. Here's a recording http://www.ebaumsworld.com/flash/play/464574/ Here's the guys homepage http://myplace.frontier.com/~pumamanor/ At the end of that page theres a few great audio files although the sound quality isn't great.1 point
-
UPDATE: FIXED THE ISSUE Hope this helps someone but it seems the culprit was the php memory limit set to 32M. I increased this to 128M and everything works fine. I added ini_set('memory_limit', '128M'); to the init() on ModulesManager.module but will sooner or later be updating the php.ini to increase this. I recommend that maybe this be included in ModulesManager for those servers with low memory limit. Yea the cache is there this is what comes up for the modules manager in the cache, also when clicking on refresh at the top right the page simply doesn't load it will post the request i see the get param but the page doesn't return anything but empty head & body. Update: The page returns this when clicking refresh Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 262144 bytes) in /home/ascentav/public_html/site/modules/ModulesManager/ModulesManager.module on line 801 Error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 262144 bytes) (line 801 of /home/ascentav/public_html/site/modules/ModulesManager/ModulesManager.module) This error message was shown because site is in debug mode ($config->debug = true; in /site/config.php). Error has been logged. Note: Debug Mode tools shows that both ModulesManager & jQueryDataTables have been loaded also when opening ModulesManager I do notice that it is pulling the number of modules because it shows this: Modules found on modules.processwire.com (319) {"id":1136,"class_name":"ModulesManager","name":"modules-manager","title":"Modules Manager","summary":"Module Manager enables you to browse the modules directory on modules.processwire.com, download, install or update them.","version":215,"module_version":"2.1.5","created":1343336504,"modified":1418136602,"url":"http:\/\/modules.processwire.com\/modules\/modules-manager\/","details_url":"http:\/\/modules.processwire.com\/export-json\/modules-manager","requires":["JqueryDataTables"],"requires_versions":{"JqueryDataTables":[">=",0]},"installs":[],"author":"Philipp 'Soma' Urlich","icon":"","likes":59,"release_state":{"id":1084,"name":"beta","title":"Beta","url":"http:\/\/modules.processwire.com\/release-states\/beta\/"},"pw_versions":[{"id":1012,"name":"2.2","title":"2.2","url":"http:\/\/modules.processwire.com\/versions\/2.2\/"},{"id":1216,"name":"2.3","title":"2.3","url":"http:\/\/modules.processwire.com\/versions\/2.3\/"},{"id":1377,"name":"2.4","title":"2.4","url":"http:\/\/modules.processwire.com\/versions\/2.4\/"},{"id":1466,"name":"2.5","title":"2.5","url":"http:\/\/modules.processwire.com\/versions\/2.5\/"}],"categories":[{"id":1078,"name":"admin-helper","title":"Admin Helpers","url":"http:\/\/modules.processwire.com\/categories\/admin-helper\/"},{"id":1018,"name":"process","title":"Process Modules","url":"http:\/\/modules.processwire.com\/categories\/process\/"},{"id":1080,"name":"proof-of-concept","title":"Proof of Concept","url":"http:\/\/modules.processwire.com\/categories\/proof-of-concept\/"}],"authors":[{"id":1050,"name":"soma","title":"soma","url":"http:\/\/modules.processwire.com\/authors\/soma\/"}],"project_url":"https:\/\/github.com\/somatonic\/ModulesManager","download_url":"https:\/\/github.com\/somatonic\/ModulesManager\/zipball\/master","forum_url":"http:\/\/processwire.com\/talk\/topic\/1550-modules-manager\/"}1 point
-
Hi kongondo, Thanks for the quick reply and the welcome. I had actually already read the topic that you mention, and this is what prompted my need: I would like to save a "stock" field for each product, but this field would have to be calculated each time a stock movement is saved, and calculating this field is precisely what takes so much time. In the meantime, I continued looking into the problem, and I think that I came up with a solution with the following module: class PagesSum extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Pages Sum', 'version' => 1, 'summary' => 'Adds a $pages->sum($selectorString, $fieldName) function to sum the value of a specific field over a list of pages selected by a selector string.', 'singular' => true, 'autoload' => true ); } public function init() { $this->addHook('Pages::sum', $this, 'sum'); } public function sum($event) { $selectorString = $event->arguments(0); $fieldName = $event->arguments(1); // Find all the pages associated with the selector string $pageFinder = new PageFinder(); $idQuery = $pageFinder->findIDs(new Selectors($selectorString), array('returnQuery' => true)); $idQuery->set('orderby', array()); $idQuery->set('groupby', array()); $idQuery->set('limit', array()); $stmt = $idQuery->execute(); $idArray = $stmt->fetchAll(PDO::FETCH_COLUMN); // If no pages were found, return 0 if (count($idArray) == 0) { $event->return = 0; return; } $idString = implode(',', $idArray); // Get the table name for the given field name $field = $this->fields->get($fieldName); // If no field with this name is found, return 0; if (!$field) { $event->return = 0; return; } $tableName = $field->getTable(); // Run the SUM query $sumQuery = new DatabaseQuerySelect(); $sumQuery->select("SUM(data)"); $sumQuery->from($tableName); $sumQuery->where("pages_id IN ($idString)"); $stmt2 = $sumQuery->execute(); list($total) = $stmt2->fetch(PDO::FETCH_NUM); $event->return = $total; } } In my tests, it is about 60 times quicker to calculate the sum with the function $pages->sum($selectorString, $fieldName) than looping over the pages (for about 12000 pages). I would appreciate any feedback, in case there are any other optimizations to be achieved, or any errors I haven't thought about. And I hope that this might maybe be useful to others too!1 point
-
1 point