-
Posts
17,231 -
Joined
-
Days Won
1,697
Everything posted by ryan
-
"Allowed memory size" issue when working with many large $pages calls
ryan replied to evanmcd's topic in API & Templates
Those API calls are probably loading all 10k pages since you are doing the count after the query. Try changing it to this and it should fix everything: $totalUnpublished = $pages->count("template=entry,status=unpublished"); $totalPublished = $pages->count("template=entry, parent!=/entries/rejected/"); $totalRejected = $pages->count("template=entry,parent=/entries/rejected/,include=all"); Another way you could do it would be this (though I prefer the way above): $totalUnpublished = $pages->find("template=entry,status=unpublished, limit=2")->getTotal(); $totalPublished = $pages->find("template=entry, parent!=/entries/rejected/, limit=2")->getTotal(); $totalRejected = $pages->find("template=entry,parent=/entries/rejected/, include=all, limit=2")->getTotal(); Either of those examples were perform at the same speed (which should be very fast). -
Beyond my response from your PM, I'd also suggesting doing a redirect after the logout, just in case that's causing any issue here. if($input->get->logout) { $session->logout(); $session->redirect('./'); } Also make sure that no data is sent before the logout and/or redirect. Cookies (sessions) and redirects happen as a result of http headers, which are sent before any output. Once output is sent, headers are no longer applicable. So you could get unusual behavior if you'd output anything before the $session->logout() call.
-
Your executeFetch method will only get called if the URL is /path/to/your/page/fetch. Since Process modules make use of URL segments, make sure your template has urlSegments enabled. I think what your executeFetch method is doing looks fine from the aspect of it returning JSON. Note that PW is going to output that JSON in the middle of an admin template unless the request actually comes in through ajax. So if you see JSON in the middle of PW's admin template, don't worry, just try it again pulling the data from ajax and PW should detect that and only output your JSON.
-
Attached is an update to /wire/modules/Fieldtype/FieldtypePage.module that lets you do this, once you replace your existing file with the one below. You should be able to specify just about any native or custom page field after the dot, like above (where we're using 'title'). If anyone can test it out to confirm I'd appreciate it. I'll commit to the source after testing a little more locally too. FieldtypePage.module This type of syntax is already used by repeaters. But if you mean something like: "repeater_field.referenced_pages.title%=$query", I don't think the attached update would let you do that, though havent' tried. If it doesn't, it's probably not much of a stretch to support it though.
-
I think you can do this with just having a single page. When your module creates your template, assign this property to it before saving it: $template->altFilename = 'admin.php'; That will make your template use the existing admin template when it comes time to render the page, hopefully executing your process along with it. If you want to test it out before going in the code, this is also a property you can set from PW's template settings. Edit the template and then click on the 'advanced' tab. You'll see a setting there called 'Alternate Template Filename'.
-
Just for clarification, the intended search would be for: (body OR title contains $query) OR (referenced_pages contains $my_referenced_pages) and not this? (body OR title contains $query) AND (referenced_pages contains $my_referenced_pages) In ProcessWire you can't do the first one in 1 find(), at least not yet. Though the second one you can do and is pretty common: body|title%=$query, referenced_pages=$my_referenced_pages I'm hoping to make this possible pretty soon (but it isn't yet): body|title|referenced_pages.title%=$query
-
Module: Video embed for YouTube/Vimeo (TextformatterVideoEmbed)
ryan replied to ryan's topic in Modules/Plugins
I wish that was me. You are thinking of Marty. I've not launched a bunch of projects lately, not by a long shot. The ones I posted about in Pub a month or two ago were done over a long period of time. -
What would probably be best is to abstract it to a $this->copy($url, $dest); function that checks what's available. If CURL is available, it delegates to $this>copyCURL(). If not, it checks if ini_get(allow_fopen_url) and calls $this->copyPHP(). Or something like that. ZipArchive is another thing that may not be in all installations (PW uses exec('unzip') instead, which also isn't universally available. If the file system isn't writable, using PHP to FTP to localhost is another option to perform installation. You are right, lots of potential factors. But probably best to start simple and require ZipArchive and a writable modules dir, and then expand upon that later. Do you mean like uploading a ZIP file of a module? Looking good! I just let my Modules Manager update itself, which is always fun. Language packs are already installable from the admin, so don't think we need to do anything there. Admin themes would be a fun thing to have installable in the modules manager, longer term probably. Site profiles won't ever need to be installable through the Modules Manager, since they get installed before the site exists.
-
Good suggestions. This makes sense to me. I've added the code to add a class of PageListItem_[template name] to each item. Going to test a bit more locally and commit early this week. Thanks, Ryan
-
That's a good idea by Soma. But I don't see any reason why these functions shouldn't be hookable in ProcessField, so I've just made them hookable. The following are now hookable: buildEditForm buildEditFormBasics buildEditFormCustom buildEditFormAdvanced buildEditFormDelete buildEditFormInfo I've also added a function to ProcessField: getField() -- returns the current field being edited (as set by buildEditForm) So if you make a hook into one of the above, you'd retrieve the field like this: public function yourHookFunction(HookEvent $event) { $process = $event->object; $field = $process->getField(); // ... }
-
Regarding learning OOP, WillyC actually makes a good point there about something that is kind of helpful in learning it. Thinking about interfaces in code the way you do interfaces with the objects you interact with in real life. Objects are meant to be self contained things that have defined inputs and outputs, hiding the [potentially complex] details of how it happens and just giving you predictable inputs and outputs. If you start relating objects in real life to their equivalent in code, things start to come together a little easier and it gets your mind in the right place. Stepping back from his toilet example and use something like a faucet instead. The inputs are knobs that set the temperature and strength of flow. And the output is water at the temp and flow you set. $faucet = new Faucet(); $faucet->setTemp(97); $faucet->setFlow(10); echo $faucet->render(); (or something like that)
-
Who's using octals? The module version number was never meant to be octals. It's just meant to be a plain integer. If you've ever seen me put leading zeros in a version number (whether in modules or in examples) then it was by mistake (let me know where so I can fix it!) If you want to have version 0.0.1 then use: 1 If you want to have version 1.0.0 then use 100 If you want to have version 2.1.1 the use 211 Does this make sense? Or am I misunderstanding the question?
-
ProcessWire Conference 2013 / London / Cambridge
ryan replied to ryan's topic in News & Announcements
Thanks, glad to hear there is some interest. I'll keep looking into it more here. Cost is certainly a big factor to me too. Just flying over there may be beyond my budget resources, but not going to worry about that now. So if we find the costs could be a hindrance to anyone, then we'd look at alternatives or delay further in the future. However, my understanding from this client (who is also family, btw) is that it really is the whole point of doing it this way… Kind of piggy-backing and sharing the expertise, planning and resources of another conference to get the most value. Planning this kind of stuff really isn't my thing, and so would need someone to take care of all the details, which is what they do. I'm also not particularly comfortable as a presenter (I like to type, not talk ), but am more interested in rising to whatever is best for growth of the ProcessWire project, so figure this is a good opportunity worth exploring. -
Soma, an alternative to libcurl is to just use copy(). At least, that's how ProcessWire does it with images that you add() from remote URLs. It's true that it requires PHP to have allow_url_fopen setting enabled. But then again so does file_get_contents(), which you are already using with a remote URL. copy("http://remote file", "local file"); I'll be happy to help, though I think you've already got as much "advanced stuff experience" as anyone here. I don't want to take over, just want to collaborate and work towards getting it in the core (if you are open to it), but you stay in charge of it. (I already got too much to keep track of). This will be one of the best and most important core additions to date. It literally eliminates the need to add future optional core modules. For instance, there would no longer need to be core-but-uninstalled modules like LanguageSupport, FieldtypeRepeater, etc., since they could be installed just as easily via the Modules Manager. I am wondering how we should integrate this into the existing Modules page in the PW admin? I'm thinking this should probably replace the current Modules list in PW, but there would need to be a clear differentiation between what's installed and what's installable (maybe each as a tab on the modules screen). The "what's installable" screen should probably start out with a category selection, since I'm anticipating the installable modules to get into the hundreds and eventually thousands, so needs to be more scalable than a long linear list. Just initial thinking and ideas. You may have already put a lot more thought on this stuff than I have.
-
It looks like hotlinking images from the forum also doesn't work. Not sure if it's the same issue with whether the user is logged in, or if it's just that the URLs are so long and complex that BBCode no longer recognizes them as valid image URLs. During one of the next updates to the directory, I'm hoping to add file upload capability for image and archives, for the situations where GitHub may not be in use. I don't know? Curious if anyone else does. I don't think I've worked with octal numbers in PHP before.
-
This is something we had on the roadmap a long time ago back when it was just a forum thread. I think it's a good idea for sure. It would be nice to have the PW API fully available via javascript. It seems like there aren't many hurdles to overcome with it, at least to implement the $pages API variable for read-only access. It could use something like the Ajax page search API (but built for the front-end).
-
TwitterMarkupFeed-Module: Problem with links
ryan replied to geniestreiche's topic in General Support
It looks to me like that may be a different kind of feed than what the MarkupTwitterFeed module was designed to use. This particular feed is putting HTML inside of RSS, whereas the Twitter Feeds I've worked with were consistent with the text of the actual tweets (no HTML added to them). I would guess that the tweets with links are failing because of the extra HTML added to the links. I am also guessing that this particular RSS feed was designed for a front-end AJAX search function. Maybe there is a GET variable that can be specified to have them turn off the HTML they are adding to it? If not, it might be better not to use this particular feed, since it doesn't seems to be setup for another purpose. One other thing you could try would be to specify "false" for the linkUrls option to the module: $t = $modules->get('MarkupTwitterFeed'); $t->linkUrls = false; -
MarionRaven I think you are right about the reason why it's not working, because of the find(). Though not positive why it would work in the include & bootstrap context you mentioned. But I think it may be as simple as updating the two find() calls in RunSchedulePages() to have an "include=all" added to their selectors, i.e. $unpublished = wire("pages")->find("status=unpublished, publish_from<$time, include=all"); $published = wire("pages")->find("status=published, publish_until>0, include=all"); If you test it out, let us know. My only concern would be that "include=all" may override the "status=", but hopefully not. If it does, try instead to add "check_access=0" rather than the "include=all".
-
There's nothing wrong with your code, but just a difference of context here. The issue is that a few of the in-memory selectors sometimes aren't as smart as the DB-driven ones. Your code quoted above is an in-memory find() provided by the WireArray class. It is used throughout the system, and it performs literal string comparisons. Whereas the DB-driven one is sending out queries to be answered by MySQL, often with a lot more context than string comparison. Most of the time, the two should perform the same, so this is one instance where they don't. It may be something I can account for. I hadn't noticed this before because it's somewhat rare to do this type of in-memory find() where you are finding/filtering pages based on pages within pages. In-memory finds and filters aren't ideal because it usually means that more pages have been loaded into memory than were actually needed. So it's preferable to avoid situations that result in post-filtering or post-finding, when possible. In your case, it sounds like you are going to use all the pages, but just using find() to group them differently. If you want to stick with that route, I would do this: $the_list = new PageArray(); foreach($the_articles as $a) { if($a->article_categories->has($the_cat)) $the_list->add($a); } The above also reveals the technical reason why the in memory find failed. The string value of $article_categories and $the_cat won't match unless $article_categories only has 1 category and it is $the_cat. That's why we had to use has() to compare them, which is something that WireArray::find has no contextual awareness of. I'm going to see if there is some way to make them work the same. Thanks for bringing it up.
-
1. Field names 'start' and 'end' are reserved words in ProcessWire selectors, so probably not good to use as field names. Actually I'm surprised it let you create fields with those names (I need to fix that, if those are real field names you put in here?). Still, I'm not sure if that would necessarily be a problem in your code example working, but it's worth renaming those fields to save any potential issues. 2. I don't see anything here that checks if the form was submitted, so it looks to me like this block of code would blank out everything on the $r page every time the form is viewed. The only time it would populate data is when it was submitted. But of course, as soon as it's viewed again, it would make it blank. So I think you need something like this, immediately after the code that displays the form: if(!$input->post->submit) continue; That would prevent it from executing all the code that populates the page below it, unless the form was actually submitted. 3. If there is more than 1 item in $hahfmember or $h, then they are all going to end up with the same values after the form is submitted. That's because you are repeating the same field names in your form, with no way to differentiate them, so they are basically overwriting each other. I recommend doing something like this: foreach($h->rp as $r) { // not that $r in a string resolves to the id, so it's the same as $r->id echo "<input type='text' name='cost_$r' value='{$r->cost}' />"; // and do the same with your other fields if(!$input->post->submit) continue; // if form isn't submitted, this skips everything below $r->of(false); // turn off output formatting $r->cost = $input->post("cost_$r"); // and do the same with your other fields } 4. I think it's always good to sanitize any input, whether using PW's $sanitizer or something else. While it's true that setting values to a page also sanitizes them automatically for most fields, I think it's always good to do your own sanitization specific to the needs of your context. I don't know what your field types are so can't say exactly what to do. So here's a few examples: // if cost is an integer $r->cost = (int) $input->post("cost_$r"); // or this to ensure it's a positive integer $r->cost = abs($input->post("cost_$r"); // or this if cost is a text field $r->cost = $sanitizer->text($input->post("cost_$r")); // or this if it's a textarea field $r->cost = $sanitizer->textarea($input->post("cost_$r)); You could go even further and validate that the values were within expected ranges, etc. 5. If you don't have something like an entities output formatter defined for all your fields that are getting populated in the form, you probably want to encode them with htmlentities() before outputting each in the form. This ensures that a quote character like " or ' wouldn't break the output. And of course ensures your field doesn't get used for malicious purposes: echo "<input type='text' name='cost_$r' value='" . htmlentities($r->cost, ENT_QUOTES, 'UTF-8') . "' />"; If it's an integer fieldtype, or a text field with a textformatter on it that already does this, then you don't need it (as it would double encode it).
-
One of my clients specializes in putting on conferences/summits around the world, primarily focused on architecture and sustainable design. I mentioned to them how some users here (starting with Netcarver) had expressed interest in a ProcessWire meetup or conference in the UK. This client does conferences in the UK every year and they are extremely enthusiastic about ProcessWire and interested in helping us to put on a conference by letting us collaborate with their conference and share the same venues and accommodations. This would help us benefit from their expertise in putting on conferences (which they've done for more than a decade), as well as help [significantly] on costs in reserving the venues, food, hotels. I have worked with this client since 1994 (18 years), so have a very high level of trust with them. The conference would be in August 2013 and be 1.5 days in London at a major ad agency, then we'd step on a train for an hour or so and do the rest of the conference in Cambridge at Kings College for another 1.5 days (total 3 days). This would be a small but relatively formal conference with presentations and workshops covering everything ProcessWire, design and web development. We'd cover topics at a higher level than you'd find anywhere else in the world. I don't yet have an idea on costs except to say that we'd find a way to make it accessible to as large of an audience as possible, and it would be completely non profit, food and accommodations (for those that wanted it) included. Yet, it'd still be higher class and more personal than any other webdev conference. This is about a year out, so I'm interested in finding out who'd be interested in this. Please 'like' or reply to this post if you would be interested in attending (or presenting) at this conference.
- 57 replies
-
- 19
-
-
I should probably make the module 'add' page use an integer rather than a string. But the two can be translated to/from each other (integer -> string). 1 = 0.0.1 10 = 0.1.0 100 = 1.0.0 111 = 1.1.1 I will plan to add this clarification to the module add form.
-
I agree with everything Pete said! Tested out here and worked beautifully. Such an easy way to install modules. Great work Soma! I was actually experimenting with something similar here this morning before work. But my version was limited to pasting in the ZIP file URL and having it install from that. Yours is so much farther along. So let me know what I can do to assist or collaborate here. I agree that it would make sense to have this buit in as a core functionality once stable. A few minor things to mention: 1. It installed under /processwire/modules/modulesmanager/ rather than /processwire/setup/modulesmanager/. So I moved it to Setup. Your instructions mentioned it would install on Setup, so just wanted to mention this in case anyone else tries it and can't find the Modules Manager. 2. Your uninstall function is named "deinstall" rather than "uninstall". As a result, it won't get executed when the module is uninstalled. 3. Rather than using mkdir() and $this->config->chmodDir, you can use the wireMkdir() function if you want to (which pulls from $config->chmodDir on it's own). 4. There are some chmod(0777)s in there. Should this use $config->chmodDir instead? 5. For lines like this (below), I'd suggest comparing the page name rather than the title, just because I can see tweaking headlines, but not changing page names. Though what we'll probably do is just setup the web service to have an option to exclude modules that aren't auto-installable, so that you don't have to perform the check at all. if(in_array('Language Packs',$categories)) continue; if(in_array('Admin Themes',$categories)) continue;
-
Welcome to the forums er314. I think what you want may be this: $the_cat = $pages->get("template=one-category, title=cat1"); $the_list = $pages->find("template=one-article, article_categories=$the_cat"); It sounds like you might be performing this from your one-category template, so in that case you could just do this: $the_list = $pages->find("template=one-article, article_categories=$page"); In addition to the above, you might want to specify a "sort" in your selector, like "sort=date" (if you have a field called that) or "sort=title" or something like that. Though if you change your call to something like this, then it would automatically sort by whatever is defined with the /articles/ page: $the_list = $pages->get("/articles/")->children("article_categories=$page");
-
Nico, have you had a chance to try adding modules to the directory again? We've had a lot of stuff added, but I don't think any of yours are in there yet. Let me know if you are still running into any issues with the add module page.