-
Posts
17,307 -
Joined
-
Days Won
1,725
Everything posted by ryan
-
I tried it out today and seems to work great! Definitely a nice tool for anyone that wants to work with HTML markup in their textarea field. Thanks Nico!
-
If I recall correctly, SimpleXML doesn't work with the properties that have colons in them. But you can fix that by replacing the colon properties with underscore properties in the XML data. So in this case, you'd want to add this line in the load() function: <?php public function load($url) { $this->items = new WireArray(); $xmlData = $this->loadXmlData($url); $xmlData = str_replace('dc:creator', 'dc_creator', $xmlData); Or you may be able to cover all the colon properties at once using a regexp like this: <?php $xmlData = preg_replace('{(</?[_a-z0-9]+)[_a-z0-9]+>)}', '$1_$2', $xmlData); What that does is convert properties like <dc:creator> to <dc_creator> so that SimpleXML will understand them and likewise you can access them in the module. Let me know if this works for you. I'm not in a place where I can update the source on this module today, but will plan to add something like the above soon. I don't know why the <comments> property wouldn't be getting parsed, as that appears to just be a string (URL). I need to test and experiment with that one to find out why.
-
Progress on ProcessWire 2.2 and overview of multi-language support
ryan replied to ryan's topic in Multi-Language Support
Soma, thanks for testing this out. For the purposes of translation consistency between languages (especially with the default language), I think it's good to be able to see them all at once ... at least as a default. But I think it will depend on the use. Right now I also question how useful multi language fields will be in practice, especially since we recommend multi-language trees instead. But it's also one of those things we can't do without because we need page references to have language support. Otherwise, using page references would be a lot more work. But because I'm not yet sure how much people will be using these multi language fields beyond this, I think it's best to start simple with the UI, and build from it as the practical uses become more clear. An option for tabs and per-user are good ideas that I'm sure we'll implement if people start using these a lot. I'm having the same issue-it's a bug. Should have it cleared up soon. Thanks, Ryan -
I haven't noticed any speed issues on the site here. There are all kinds of factors that can affect the speed at which a site loads, so best to track down what it is first. If the site loads quickly for one person and not another, chances are there is a network issue between the host and user, or there is a factor on the site where performance is affected by the users' software or hardware (i.e. JavaScript execution speed). If a site is consistently slow for most users then more likely the web host, server or the site itself and it's use of server resources. When browsing the site I monitored the request times in firebug and there is an above average 'wait time' between request and response on the page's URL. However, it's not something I would have noticed. But that may point to some heavy lifting happening at the server, whether in PW or any number of other factors. When it comes to PW, it will let you consume a lot of resources very easily, so you do have to take care sometimes, especially with larger sites. For instance a call to $pages->get('/blog/entries/')->children could load all blog entries if you didn't specify it with children("limit=n"). Likewise, siblings/next/prev functions are good to avoid on a page with hundreds of siblings. With great power comes great responsibility. PW will happily load up a few hundred or more pages, but it's not something you want to do if you don't need to because it will affect performance. And even when you need to, it's good to reduce the number of times. One way is by using the MarkupCache module, especially for things you are having to generate on every request. Likewise, the template caching is good to use in instances where you don't need to change something on every request of a page (ie don't need randomization or second by second updates). But my opinion is that it's best to use caching only after you've made your other code as fast as it can be and have made sure you aren't loading pages you don't need to. These are just general guidelines and aren't much of a consideration until things get big. This site is at a size (with several hundred blog entries) where some of these scalability considerations should be observed. But it may or may not be applicable in this situation. The site performs reasonably well for me and I would not have ever noticed it as slow. But then again, maybe I was the only one accessing it at the time. Anytime anyone wants me to look at your code for potential bottlenecks I'm happy to. Feel free to post in the forum or privately to me. Most issues that would affect scalability are simple to fix because PW is designed to really sing at the larger scale and just requires occasional tweaking to how you use the API.
-
Thanks Pete, I'll take a look at this and should be able to change the BG color. PNGs should be okay, as I think we've fixed something similar with PNGs in the past. GIFs are generally terrible for any kind of resize and I'd recommend avoiding them in any situations where you need to be creating size or crop variations. But I know it's not always a choice. Hopefully we can get the transparency working with them.
-
I agree this doesn't need the fieldtype at present since it could be designated as an input for the existing textarea. However, there's no harm in giving it it's own fieldtype. Some of the expansion potential may need it. Nico, if you want to make it PW 2.2 ready, look at the thread on module dependencies in the announcements board. The fieldtype+inputfield is a good 'requires' and 'installs' dependency to use with the new options. Though all are optional.
-
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.