Jump to content

ryan

Administrators
  • Posts

    16,867
  • Joined

  • Last visited

  • Days Won

    1,571

Everything posted by ryan

  1. Thanks Rob, got your message and will take a closer look today. Regarding the functions you mentioned: • wakeupValue() converts a file from a basic storage type (typically an array) into it's representation in ProcessWire. Most often this is used to translate the raw value from the DB into the live value for runtime. • sleepValue() does the opposite of wakeupValue() and translates a runtime value back to it's basic type for storage. If you are just dealing with a simple type like an integer or a string that are represented in the database exactly how they are at runtime, then wakeupValue() and sleepValue() don't need to do anything at all (other than return the value they were given). So these functions really only come into play when the field's value has to be stored differently than it would be presented at runtime. This would be the case for anything that is presented as an object at runtime. Since an object can't just be "stored" and still have its components be searchable and sortable in a database, it needs to be translated to/from fields in a DB table. Likewise, if you are sending object field values to/from JSON/XML web services, you probably want that object represented as an array, so that it can be encoded by XML or JSON. • sanitizeValue() is entirely unrelated to the other two functions (though you may see it called in series with them). But it does nothing other than sanitize a value that is assigned to a $page. So lets say that you have a field called 'myfield' and this API call gets executed: $page->myfield = 'my value'; That value gets passed through the sanitizeValue() method for whatever fieldtype is used by 'myfield'. After passing through sanitizeValue() it gets set to the $page. The sanitizeValue() method is just a way to ensure that invalid data doesn't get assigned to the page. So if the fieldtype used by 'myfield' expects it to be a string, then its sanitizeValue() method should ensure that whatever it returns is a string, regardless of what it's given. Or if you want, you can have it throw an exception when it receives invalid data. But here's what a sanitizeValue() method might look like for 'myfield': public function sanitizeValue(Page $page, Field $field, $value) { if(!is_string($value)) $value = (string) $value; return $value; }
  2. That's correct, the .htaccess file is blocking access to /site/templates/ (and below), but only for files with these extensions: php, inc, htm, html, tpl. This is for security, since files in there are meant to be parsed by ProcessWire, not direct browser access. As long as its not one of those extensions above, PW shouldn't be blocking it. Though you may prefer to move it outside of PW's templates dir and perhaps into something like /site/tinymce-templates/. I agree with this -- I think it's far preferable to use PW fields for this kind of stuff. It's definitely not a best practice to use something like TinyMCE for keeping structured data. (Though technically, I suppose the markup coming from TinyMCE could still be considered structured data if it's kept semantic.) This approach seems like something that one would do in some other CMS that doesn't have the ability to adequately manage custom fields. I don't understand using the approach here, but I also like to see that this can be done with TinyMCE. I'm sure there are times when this could be handy. I also know that everyone in this thread knows what they are doing and are already familiar with when and where they want to use PW fields. So I'm sure there are good reasons for taking this route. For instance, if you knew you never needed the data to be searchable at the field-by-field level, and didn't need it to be portable beyond the current need, then you might reduce the load of custom fields in your system by taking this TinyMCE template approach.
  3. Adam, the page render() method doesn't know if it's being called upon to render a page for a request, or being called by the API somewhere else. Bust since the render() method basically just executes your template and captures the output, you can have your template look for some variable that tells it to render a 'thumbnail' version. In this example, I assign a 'useThumbnail' variable with a value of true to each photo page, and then call its render() method: $photos = $pages->get('/example/page/get/')->children('template=photo'); foreach($photos as $photo) { $photo->useThumbnail = true; echo $photo->render(); } Then in your 'photo' template, check for that 'useThumbnail' trigger: $img = $page->image; if($page->useThumbnail) $img = $image->size(150,80); echo "<img src='{$img->url}' alt='{$img->description}' width='{$img->width}' height='{$img->height}' />";
  4. Rob, feel free to email to me and I can try out this weekend and hopefully come up with an answer. This is one I probably need to step through the code as it runs. But If you are getting WireArray(0) somewhere, you may want to nail that back to a regular array since that is the value you want to work with. You can get a regular array by calling the getArray() method from any WireArray.
  5. Thanks Alan - I'm limited to mobile today but will do more research on that error when I get back to the computer this weekend. Thanks for saving that DB, that may be helpful to determine what happened.
  6. Welcome to the forums Ben! I would suggest not using the skyscrapers site profile because that will only work with PW 2.0 and that version is now very out of date and not a good one to use for benchmarking. Though I don't think that has anything to do with the error you are experiencing, but want to make sure you are using an up-to-date version. I do plan to update the skyscrapers profile to work with PW 2.2+, but haven't yet had the time to do it. So for now, I would suggest using PW 2.2 and the basic site profile that it comes with. I've been building a list of people waiting for the PW 2.2 compatible skyscrapers profile and happy to send it to you when it's ready--just let me know. Netcarver: thanks for your great responses here. I'm really impressed with your knowledge on this stuff.
  7. I'm still wondering about this, since it sounds like its not working correctly here. What is the scale of pages in your site using the template 'cool-page' and what auto join fields does that template have? I'm just trying to find out as much info as possible to be able to reproduce it. Not sure I understand the question 100% so let me know if i don't answer it right. The class::method syntax when you add the hook is just a way of communicating to PW that you want to hook all current and future instances. Kind of like a jQuery live() event. This is consistent to how you'd usually refer to a class::method in documentation, outside of a specific instance. If you only wanted to hook one instance then the syntax would be $objectToHook->addHook('method', $myObject, 'myMethod'); and $myObject is most commonly $this.
  8. Thanks for the follow-up on the solution you found for this.
  9. Thanks Bill, I think the main difference is just PHP5. There is a lot about PHP5 that really benefits the ability to build simpler plugin systems. WP and others are still built around a PHP4 idea of plugins, probably for legacy support reasons. It doesn't really matter much which you use. But here are a couple factors. I definitely like the readability of $this->apiVar better, but the truth is that using wire('apiVar') is more bulletproof. In order to use $this->apiVar, you have to be in a class that extends Wire, and you can't take control over the __get() method in the class. Or at least if you do, you have to make yours call parent::__get() when your class doesn't have a handler for a given variable. So if you are using wire() exclusively, you really don't have to worry about things when you override a __get() method. Also, wire() doesn't have to pass through any comparisons, as it's singular purpose, so technically a little more efficient. Lastly, wire() can be used in procedural functions, and in classes that don't extend Wire, making it portable for use anywhere in your site's code. Still, it may not feel right to rely on a procedural function to access API vars. But if you can get past that feeling, it actually makes a lot of sense to use it. It's kind of like PW's version of jQuery() or $(). Using wire() is newer syntax, and not something you could do in the original PW 2.0. So I haven't standardized on one or the other, and use both interchangeably, and PW will always support both. Also want to note that PW passes all the API vars to your template files, so you don't have to use wire() or $this, and instead you can just access them directly, like $pages.
  10. Not a problem Soma. I'm just glad you were able to find a fix for the other issue, because that one was a lot harder to fix than this one. Also, my experience with TinyMCE is that any time I fix something, I break something else, but don't usually find out about it right away. So this just seems to go with the TinyMCE territory.
  11. I don't know of a way that you can do this at present (short of making a module to do it). But if you need text formatted in a certain way, it's best to split the components of it into separate fields so that you can ensure that any formatting that happens is separated from the content.
  12. You are right, looks like it's not working with Safari for some reason. Just confirmed. I will put this in the issue queue. Thanks, Ryan
  13. I think you are on the right path here. The page that Jasper and Marc linked to is good when working with larger scale stuff (and smaller too), but I'm not usually that disciplined on smaller stuff. One alternative would be to bundle your news_posts.inc into a function, and keep a file with that function and any others you might need. I usually call mine tools.inc. The function would look like this: /site/templates/tools.inc function listNews($news) { $out = ''; foreach($news as $item) $out .= "<p>{$item->title}</p>"; return $out; } Your template files that need to list news (or use your other functions) would include('./tools.inc'); at the top, and then they would call the function when/if they needed to list news: echo listNews($pages->get('/news/')->children('limit=5'));
  14. I can't seem to edit my last message without having it convert everything to entities (something not working right with the forum). I just wanted to mention the class line should be this instead: class YourModule extends Wire implements Module {
  15. This is not what it's supposed to do. This is probably the most common selector usage there is. Need some more information to determine what's going on here. Try turning on debug mode (/site/config.php) and edit the $config->debug line to be true. That should at least give a better sense of what error is getting thrown. Though if not, tell me more about this case. How many pages are there using 'template=cool-page' and how many 'autojoin' fields are part of it? If you are dealing with hundreds of pages you may want to place a limit=n on it. This looks like a good approach. If you want to add your getAttr() method directly to the PageArray, so that you can call it like this: $IDs = $randomChildren->getAttr('id'); ...you can do it with an autoload module: class YourModule implements Module { static public function getModuleInfo() { return array( 'title' => 'Your Module', 'version' => 100, 'summary' => 'Adds a getAttr() method to all PageArrays', 'singular' => true, 'autoload' => true ); } public function init() { $this->addHook('PageArray::getAttr', $this, 'getAttr'); } public function getAttr(HookEvent $event) { $pageArray = $event->object; $key = $event->arguments[0]; // ...the rest of your code goes here... $event->return = $pageKeys; } }
  16. What browser and version are you experiencing this in? Also note that the way you are changing settings makes it specific only to the template you are editing the field from. If you want to change the field settings outside of that context, you'd change them under Setup > Fields. I'm thinking you already know this, but just wanted to mention it just in case.
  17. It looks like this is a new issue that came as a result of our recent fix for the links not being editable in some instances. A text() in jQuery needed to be an html() instead -- easy fix. Just committed. This one I can't duplicate. Though if it was possibly related to the other issue, then that may be why. Let me know if it still does it to you after the other issue is fixed, and if so, in what browser (I tested in Chrome 17). Thanks, Ryan
  18. Updated to support negative values in the timestamp, and committed. It had to do with validation rather than the DB field type. We're using a MySQL datetime field for storage, so that isn't bound to the limits of timestamps. We're using timestamps just on the PHP side for sortability, sanitization and abstraction from a defined date format.
  19. I'm also confused about what the repeater would be here for. If you are wanting to support <title> and <meta description> then I would make two text fields with 255 character maxlength: browser_title meta_description You could make those two global, but I would instead suggest having your templates populate those fields like this: <title><?=$page->get("browser_title|title"); ?></title> <meta name='description' content='<?=$page->get("meta_description|summary"); ?>' /> Using that approach, it'll attempt to use a "browser_title" or "meta_description" field if they are present and populated. If not, it'll default to using the "title" and "summary" field. That way you can add/populate the "browser_title" and "meta_description" fields to your templates as you need them. Otherwise, you'll end up having to populate all of them manually, rather than just focusing your attention on the ones that matter most. I usually keep browser_title and meta_description fields on my homepage template, and templates used by any other major pages (like top level nav stuff). And then it use the title and summary fields for everything else.
  20. In that fictional example there are two find() operations, so those aren't going to happen in 1 query, unless the results of 1 are already cached. If I recall, this should work (though not at a place to double check): $pages->find("question.name=yes"); But I want to point out that query counting is usually a waste of time. And I used to do a lot of it, up until I read High Performance MySQL. MySQL will execute a 100 simple queries faster than it will 1 heavy one. So performance usually has much more to do with query quality and proper indexing than query quantity. This is not the way I was originally taught, and not how I worked for many years, so it took me awhile to get it. You can always $db->query() and join the original example into 1 query, making sure that everything happens using an index, but you may or may not see any tangible benefit for your efforts. If there is some real performance bottleneck that could be resolved by querying directly, I still do it, though it's pretty rare. Also note that layers on top of MySQL are not unlike layers on top of languages. C++ is built on top of Assembler, and PHP is built on top of C++. PW is a layer on top of MySQL and PHP. It's possible to make lower layers perform faster than higher layers, if you know your way around them. Every layer is a compromise that has to be compared against the need. I know my way around MySQL and PHP, and for me PW lets me develop stuff 10x (or more) quickly than I could without it... and it's rare that I think it's costing me anything in performance. But if I had a project where maximizing the performance out of MySQL and PHP took precedence over all other factors, then I would keep out all other layers (no CMS, frameworks or other libraries).
  21. Michael, thanks for the description. It should be okay to use multi-language fields in a repeater (at least I have before), but it's been awhile. I will locate whatever the issue is and fix. There is an instance there where both repeater and LanguageSupport hook into the same thing, so could be that I need to add a load priority to that (that's my initial guess anyway). Antti has sent me a site profile to test so I hope to be able to reproduce the non-working language alternate fields and have a fix for that shortly.
  22. Thanks Nikola, I got it working and definitely going to add CodeMagic to the core. The current HTML button is pretty much useless in my opinion, and it's one of those things that causes me trouble almost every day. I wish I'd known about CodeMagic much sooner, this completely solves it. Diogo I'd like to give more lovin’ to TinyMCE, but I lack the expertise and time to do all the things we'd like to do with it in the short term. Though learning about CodeMagic from Nikola just brightened my day a lot. I'm hoping that eventually we'll find others that wants to help with or take over development of the TinyMCE Inputfield in ProcessWire. Taken on it's own, TinyMCE is a bigger and more complex software that ProcessWire itself. Since TinyMCE is 1 Inputfield of many in ProcessWire, I have to be careful not to let it take over too much time from the rest of PW. TinyMCE will gladly take a full day to figure out a very small thing. I'm certain there are others that can do the TinyMCE stuff better than I can. But I'm going to do my best to keep mastering it either way, and put in incremental improvements as we go.
  23. Good idea, I just renamed it to: "ProcessWire Forum: Latest Posts"
  24. I think that I can add the necessary hooks to support this. Overhead with high traffic functions is always a concern with hooks, but did recently figure out a way to do it in a way that avoids any overhead unless/until a hook is actually active. So it should be possible to make something like $db->query() hookable. I will take a closer look at this.
  25. I would avoid making a repeater field global, because then it'll require every template to have that repeater field. I can't say as though I've actually tried it though. I'm not positive it would work. So if you have that need, let me know if you find it doesn't. If you don't populate any fields in a repeater, it's considered unpublished. I have the need on a project right now to keep some repeater items published and some unpublished, so currently thinking about ways to do this. I may have a solution soon.
×
×
  • Create New...