-
Posts
17,231 -
Joined
-
Days Won
1,697
Everything posted by ryan
-
Very cool Nico, I look forward to trying this one out. My computer access is currently somewhat limited, but hope to try this in the next day or so. Thanks for your work on these new modules.
-
Looks great Nico, nice work! Seems quite useful now and lots of expansion potential too. My only suggestions would be to remove the 'permanent' from the getModuleInfo on the inputfield. And move the CSS/JS loaders from the fieldtype's sanitizeValue method to the inputfield's init() or render() method. Reason for this is that fieldtypes are supposed to be independent of interactive input, whereas that's what inputfields are for. Otherwise looks great.
-
Thanks everyone, hope that you had a great Christmas!
-
Sorry I missed this in the instructions (will update later) bit this module currently requires the 'full' not 'basic' calendar. So you'd need to replace basic with full in your URL. It looks to me like your full has read access disabled. Try with the example feed if you want.
-
Really beautiful work Nico. This may be the first full-blog site in PW and its also one of the nicest Blog sites that I've seen, ever. I'm very proud to see this running in ProcessWire.
-
Hope that you have a Merry Christmas, a Fine Festivus and a crazy New Year! I'm actually hoping to wrap up PW 2.2 on the 31st of December, so if anyone gets bored over the holidays, please help me test. I would have sent you all a card, but don't know anyone's address. So I took a photo of it.
-
Given a Google Calendar XML feed URL, this module will pull it, cache it, and let you foreach() it or render it. Download at: https://github.com/r.../MarkupLoadGCal USAGE The MarkupLoadRSS module is used from your template files. To use it, you get a copy of the module, tell it what URL to load from (with the load method), and then execute a find() query with a selector string. It works basically the same as a $pages->find("selector string"). <?php $cal = $modules->get("MarkupLoadGCal"); $cal->load('http://calendar XML feed'); $items = $cal->find('from=2011-12-1, to=2011-12-31'); foreach($items as $item) echo "<p>{$item->title}</p>"; To get a Google calendar URL, you would go into your (or another) calendar on Google and click to the calendar's settings. At the bottom of the screen, you will see a section called "Calendar Address" with XML, ICAL, and HTML. Copy the XML address, and use that with this module. If you just want one to test with, use the one from my examples below: http://www.google.co...com/public/full Note: you must use the 'full' not 'basic' calendar from Google Calendar. You can identify if you've got the right one because it will end with 'full' rather than 'basic', as in the URL above. Selector Properties The selector properties you may provide to find() are: from: Starting date in any common date/time format (or unix timestamp). to: Ending date in any common date/time format (or unix timestamp). keywords: Keyword(s) to search for in the Google calendar events. limit: Max number of items to load (default = 100). sort: May be 'date', '-date', 'modified' or '-modified'. html: Set to '0' if you don't want the event description in HTML. The find() method will return the found items. You can then foreach() these items to generate your output. A render() method is also included with the items which provides some default output, if you want it. Calendar Item (Event) Properties Each calendar item has the following properties: title: The title of the event description: Detailed description of the event (in HTML, unless disabled) location: Where the event will take place author: Author of this item from: Timestamp of when the event begins to: Timestamp of when the event ends dateFrom: Formatted date string of when the event begins dateTo: Formatted date string of when the event ends See the module file for additional configuration options. EXAMPLES Example #1: Simplest example <?php // get the calendar module $cal = $modules->get("MarkupLoadGCal"); // set the feed URL: may be any google calendar XML feed URL $cal->load('http://www.google.com/calendar/feeds/3icgo6ucgvsf6bi5orld9moqqc%40group.calendar.google.com/public/full'); // find all items for December, 2011 $items = $cal->find('from=2011-12-1, to=2011-12-31'); // render items using built-in rendering echo $items->render(); Example #2: Rendering your own items <?php $cal = $modules->get("MarkupLoadGCal"); $cal->load('http://www.google.com/calendar/feeds/3icgo6ucgvsf6bi5orld9moqqc%40group.calendar.google.com/public/full'); $items = $cal->find('from=2011-12-1, to=2011-12-31'); foreach($items as $item) { echo " <h2>{$item->title}</h2> <p> <b>Date From:</b> {$item->dateFrom} (Timestamp: {$item->from}) <br /> <b>Date To:</b> {$item->dateTo} (Timestamp: {$item->to}) <br /> <b>Location:</b> {$item->location} <br /> <b>Author:</b> {$item->author} </p> {$item->description} "; } Example #3: Finding Keywords <?php $cal = $modules->get("MarkupLoadGCal"); $cal->load('http://www.google.com/calendar/feeds/3icgo6ucgvsf6bi5orld9moqqc%40group.calendar.google.com/public/full'); $items = $cal->find("from=Aug 1 2011, to=Dec 1 2011, keywords=Eddie Owen"); echo $items->render(); ADDITIONAL INFO Options See the module's class file (MarkupLoadGCal) for a description of all options in the comments of the $options and $markup arrays at the top of the class file. Handling Errors If an error occurred when loading the feed, the $cal will have an 'error' property populated with a message of what error occurred: <?php $items = $cal->find("..."); if(empty($items) && $cal->error) { // an error occurred echo "Error! " . $cal->error; } $items will be blank if an error occurs, but it will always be of the same type, so it's up to you whether you want to detect errors. If you don't, then your calendar output will just indicate that nothing was found. Cache By default your calendar queries are cached for an hour. You can change the cache time by setting the $cal->cache property to the number of seconds you want it to cache. --- Edit: Added note that you must use the 'full' google calendar feed rather than the 'basic' one.
-
I see what you mean. Well the good news is, they've fixed this in PHP 5.4 and given us the JSON_UNESCAPED_UNICODE option. But nobody's running 5.4 yet (it's in RC3). Sorry to send you on a wild goose chase, but I'm thinking it may be best to hold off on the cache field in your situation. Meanwhile, I'll keep an eye on alternate encoding methods to see if there's any other approaches we might use, at least until PHP 5.4 is mainstream.
-
You could sort by templates_id or parent_id, but so long as you want the results to be keyword relevancy sorted, I think you'd want to exclude a sort parameter and break it into two queries: <?php $limit = 50; $searchFields = "title|body|summary|headline|fakta"; $matches = $pages->find("$searchFields~=$q, limit=$limit, template!=links|admin|redirect-overview|redirect-url"); if(count($matches) < $limit) { $matches->import($pages->find("$searchFields~=$q, template=links, limit=$limit")); } You may also want to create a new field of type 'Cache' to combine your title, body, summary, headline and fakta fields. Call it 'keywords' and add it to your templates being searched. Then you can just search "keywords~=$q", and it may offer some performance benefit (at the cost of database size). I didn't understand the "template!=," part of your query. I'm not sure that does anything since a page can't exist without a template. Also, the "template!=admin" is not necessary unless the user has access to edit pages in the admin. What I mean by that is that the admin pages may show up for you because you are logged in, but those pages won't show up for other users of the site. You may already know this and just don't want those pages to show up even for you, but just wanted to mention it just in case.
-
Site says: "Unable to complete this request due to an error"
ryan replied to nikoka's topic in General Support
The query in question is the first one executed by PW and this is what you'll see if there's a DB connection error. That's not ideal, and I'm not sure how I missed that error check the first time around–I'm updating the Database class to detect connection errors and throw a more appropriate error message. That way we can see exactly why it can't connect. -
Thanks guys, let me know how it works for you. I like your ideas here, good thinking! Perhaps we just maintain another section of modules that represents the uninstalled list. At the moment I'm a little scared of an "install all" in the same request, but perhaps I shouldn't be–definitely something to think about and perhaps implement in the future.
-
How to let visitors search for "job" -- 3 character issue?
ryan replied to MarcC's topic in General Support
See here: http://processwire.com/talk/index.php/topic,159.0.html If you can't change your mysql settings, you can also use the [slower] %= selector operator rather than the *= and that will support words of any length. -
I don't know much about Magento or what the SOAP client modules are. I have a strong preference for services built around HTTP/REST rather than SOAP. But so long as it's providing the services in some form, that means that it's probably a reasonable task to integrate. Magento also seems like a pretty solid system. Though admittedly, I've tried to install and use it before and found it a little overwhelming... Drupal/UberCart turned out to be a better fit for what I needed. But I think Magento is probably stronger overall. Let us know what you find and how it goes.
-
If using $page->parent in a string context, it's actually going to resolve to the ID. But I think it's better to be clear about what property you are checking. I recommend doing this: if($page->parent->id > 1) The homepage always has an ID of 1 and that's a factor you can count on in PW.
-
This is something I don't know much about yet and need to do more research. You've got me curious. Looking at Drupal7, it looks like they do it with PHP, though only if one specifically enables some page_compression and cache options. I only see reference to it in their /includes/bootstrap.inc for serving pages from the cache. It looks like it involves checking a lot of $_SERVER variables to verify gzip support, delivering a "content-encoding: gzip" header and spitting out the gzipped data when appropriate. They create the gzipped data with PHP's gzencode function. It appears that they only use it for delivering data from the cache. That makes me think that the gzencode is potentially slow and they are caching and performing the gzencode after delivering a page where it can be picked up from the cache by the next request. What's interesting is that they gzip the cache data even if not supported by the client and they gzinflate it at runtime for clients that don't support it. I suppose this makes sense, and a good way to keep smaller cache sizes. This is something we'll probably want to implement in PW's core PageRender module at some point.
-
Thanks Antti, glad that it's working alright and that the dates imported how they should. That's interesting that your CSV file had unescaped quotes in it. That will confuse any CSV parser. What did you use to export the CSV? Nico's right that quotes should be escaped with a backslash.
-
I put in module dependencies into the 2.2 dev version yesterday, and just wanted to explain how they work, both for the user side and the developer side. What it means and what it does "Module dependency" means that when you install plugin modules, they can now require that other prerequisite modules are installed first before they are. Likewise, if one module requires another, then it prevents modules in use from being uninstalled. Ultimately this leads to more clarity in the system, and makes it easier for one module to rely upon another. Likewise, it prevents the issue of being able to uninstall one module that's actively used by another. It's a convenience and a safety. The module dependency update in 2.2 also adds the ability for related modules to establish a simple parent-child relationship. One module can say that it is responsible for the installation of another, and so you can have modules installed or uninstalled as a group. Meaning, if you installed a plugin that includes 3 different modules to operate, then PW will only let you install the one designated by the developer, and the others will be installed automatically immediately after it. The same goes for the uninstall process. How to use now Attached are a couple screenshots that show how it looks from the Modules page in PW. If you want to test out dependencies, this feature is in the "dev" branch of the current ProcessWire distribution. If you are up to date on your git pulls, or you just installed a fresh copy with git, then you just "git checkout dev" to get to it. Of course, only do this on a test or development site, not a production site. FOR MODULE DEVELOPERS Using these dependencies is completely optional from a module development standpoint. While these dependencies don't exist in the current stable version of PW (2.1) there's no harm in implementing them now, as PW 2.1 will just ignore them. To test dependencies in PW 2.2, you'll just want to switch to the dev branch as mentioned in the previous section. When to use dependencies If you know that your module needs some other module in order to run property, it's a good idea to take advantage of dependencies. Especially given how easy they are to implement. Another situation where you'd want to use dependencies is with plugins that include more than one module. For instance, a fictional plugin called "Log Master" may have an "autoload" module called LogMaster to hook into various things and log them, and another called ProcessLogMaster to display them in the admin. You don't want someone to be able to install ProcessLogMaster without first installing LogMaster. Furthermore, you might want to have ProcessLogMaster automatically install (and uninstall) at the same time as LogMaster. In this light, dependencies can add a lot of convenience for the person installing your module, and less support and documentation burden for you. Using the "requires" dependency Dependencies are defined in your getModuleInfo() function. To establish a dependency, all you need to do is add a "requires" property to the array returned by your getModuleInfo() function. That "requires" property may be a string or an array. If it's a string, it's assumed to contain just the name of one module. If it's an array, it's assumed contain one or more module names. Lets say that I was creating a "Hello World" module that required the "LazyCron" module. Here's how you'd do it: HelloWorld.module <?php public static function getModuleInfo() { return array( 'title' => 'Hello World', 'version' => 101, 'author' => 'Ryan Cramer', 'summary' => 'Just an example', 'requires' => "LazyCron" // added this line ); ); You can also specify 'requires' as an array, which is what you'd want to do if you wanted to specify that multiple other modules are required (though you can of course use an array for 1 module too): HelloWorld.module <?php public static function getModuleInfo() { return array( 'title' => 'Hello World', 'version' => 101, 'author' => 'Ryan Cramer', 'summary' => 'Just an example', 'requires' => array("LazyCron", "AdminBar") // added this line ); ); That's all that you need to do to specify a module dependency. Once you do that, ProcessWire won't let your module be installed until LazyCron and AdminBar are installed. Likewise, ProcessWire won't let LazyCron or AdminBar be uninstalled so long as HelloWorld is installed. Using the "installs" dependency If you want to specify that your module installs and uninstalls other modules, then you should add an "installs" property to the array returned by getModuleInfo. Like with "requires", the property may be a string or an array, with an array is required for multiple items. Using this property is your module's way of telling ProcessWire that it is the parent of those modules and they should be installed–and uninstalled–at the same. Like with PW 2.1, your module's install() and uninstall() methods may handle the installation/uninstallation of any other modules too... but it doesn't have to. PW will automatically install/uninstall any modules specified in "installs" immediately after your module, unless your module already took care of it. It's a good idea to specify those child modules in your "installs" even if your install() function is already taking care of installing them. That way, PW can still note the relationship in the admin. Below are examples of how to add the "installs" property to your getModuleInfo(). We'll use the LogMaster example mentioned earlier on. LogMaster.module – parent module <?php public static function getModuleInfo() { return array( 'title' => 'Log Master', 'version' => 101, 'author' => 'Lumberjack Bob', 'summary' => 'Log all actions on your site', 'requires' => 'LazyCron', 'installs' => 'ProcessLogMaster' // added this line ); ); Now you've told PW that ProcessLogMaster should be installed at the same time as LogMaster. If LogMaster doesn't install ProcessLogMaster, then ProcessWire will install ProcessLogMaster automatically after it installs LogMaster. One thing to note about uninstalls: PW will only uninstall modules that specify the parent module in their "requires". If they don't, then PW will leave them installed when the parent module is uninstalled. After all, why should PW uninstall a module that doesn't require the other one being uninstalled? But I'm guessing that in most (not all) instances where you would use "installs", you'll also want to use "requires" with the child modules, pointing to the parent module: ProcessLogMaster.module – child module <?php public static function getModuleInfo() { return array( 'title' => 'Log Master (Process)', 'version' => 100, 'author' => 'Lumberjack Bob', 'summary' => 'Displays the logged actions in the admin', 'requires' => 'LogMaster', // added this line ); ); Using the above example, this ProcessLogMaster will be automatically uninstalled with LogMaster since it indicates that it requires LogMaster, and LogMaster indicates that it installs ProcessLogMaster. SCREENSHOTS 1. This shows how the module dependencies are highlighted on the Modules list page. Note that the install option is disabled for those modules that require another to be installed first. 2. This shows the screen that appears when you click on the LanguagesSupport module. It demonstrates the group of modules (children) connected with LanguageSupport (parent) module. 3. This shows an example of a module (FieldtypeComments) that has a module requiring it (CommentFilterAkismet). That CommentFilterAkismet module is an optional component to the Comments module, so is not installed by default when FieldtypeComments is installed. Since CommentFilterAkismet requires FieldtypeComments, CommentFilterAkismet would have to be uninstalled before FieldtypeComments could be uninstalled.
-
I don't see it here but got an email about paginator get vars. Make sure you turn on 'allow page numbers' in your template settings because pagination requires that setting to work properly. It shouldn't use get vars for the page number.
-
So long as you use limit=n, where n is some number greater than 1, PW will not load any more than n pages (or select the data from mysql). So paginating your selects is a good idea. The getTotal() method from the returned PageArray will contain the total number of found results (the total that would exist had there never been a limit). So the $pages->count() does little more than add a limit=2 to your selector and just returns the result of the $results->getTotal(). That count method is more for syntactic convenience, as PW already counts anything that goes through a find(limit>1). And the instances of where one would use pages->count() are pretty rare. But optimizing the count method to load 0 rather than 2 pages is on my to do list. I'm typing on a cell phone so somewhat limited in my response here, but to recap, everything you need to paginate is already included anytime you include a limit=n in your selector and using PW's pagination is recommended, especially when dealing with large data sets. There is obvious overhead relative to pure SQL queries, but I think it's very much worth it 99% of the time for the sites we build. Enable debug mode in your config.php to see the queries (from admin).
-
Progress on ProcessWire 2.2 and overview of multi-language support
ryan replied to ryan's topic in Multi-Language Support
I put in a lot of Language Support updates today, and put in the module dependency support while I was at it. One of the bigger things added was the multi language text fields. You can create new fields that using TextLanguage or TextareaLanguage (rather than Text or Textarea). You can also convert existing text fields to/from the multi-language versions. The multi language 'title' field isn't yet ready, but close. I also haven't yet put in a lot of testing into these multi language fields, so any help testing is appreciated. Before you grab this update, I recommend uninstalling the LanguageSupport modules from your existing install (if you have them), or starting from a fresh install before testing. Also, as always, don't use the dev branch in production. Lastly, the TextareaLanguage field doesn't yet work with TinyMCE yet. It's probably a simple fix, but I ran out of time to work on it today so should have an update there soon. I currently have the find() selectors designed to match values in either the current language OR default language. So if your 'summary' field is a TextLanguage field, Finnish is your current language and you execute something like this… $results = $pages->find("summary*=Antti"); …It's going to match pages that have "Antti" in the Finnish summary or Default language summary field. But it won't match in any other languages, unless you set one of them to be your language. I figured this is the behavior that most would want, but can also make it match only in the Finnish summary (or make it configurable per-field). -
I think this will depend somewhat on what format those dates will be in from your spreadsheet (CSV). If it's a unix timestamp, or any format consistent with what PHP's strtotime() will accept (which includes quite a lot of formats), then you should be able to import dates pretty easily. I think all you'd need to do is add FieldtypeDate to the list of allowed fieldtypes at the top of the modules: <?php protected $fieldtypes = array( 'FieldtypePageTitle', 'FieldtypeText', 'FieldtypeTextarea', 'FieldtypeInteger', 'FieldtypeFloat', 'FieldtypeEmail', 'FieldtypeURL', 'FieldtypeCheckbox', 'FieldtypeFile', 'FieldtypeDate' // add this line ); I don't have a good example to test from at the moment though will try to test it tomorrow. But let me know if you get a chance to test, and if that works I'll go ahead and add it to the module permanently. Looking at it now, I'm not sure why I didn't add it before. But it's the end of the day here so my mind is tired and I may be missing something.
-
Nice update, thanks for posting!
-
I think I understand. Try modifying the settings carried by the PageArray after your find() is performed, but before your pagination is output: <?php $results = $pages=find("something=something, limit=10"); if($user->isGuest() && $results->getTotal() > 50) { $results->setTotal(50); if($results->getStart() > 40) $results->setStart(40); } // then do your pagination
-
The FormTemplateProcessor module was always intended to be a proof of concept and not much more than a starting point for people to customize and build from. At present it's not designed to deal with multiple instances of itself (though could easily be updated to). When it looks to see if a form is submitted, it is checking $input->post->submit. If you've got two forms on the same page, then they are both going to be detect that submit. A better solution would be for it to assign a unique variable (or submit button name) that goes with each form so that one can't be confused for another. When we build a proper form builder/processor, we'll definitely be handling all this stuff in the module. But until then I still think it's better to manage your own forms rather than use this module for it (unless the needs are very simple).