-
Posts
17,231 -
Joined
-
Days Won
1,699
Everything posted by ryan
-
That's correct. Anything set to a $page passes through sanitizeValue, regardless of where it comes from. But I suggest that you ignore the sanitizeValue method for now, because there is no reason to implement it at this stage (unless you've extended another Fieldtype that does something with it that you don't want). I'm not sure that I understand exactly what you are saying. But your sanitizeValue shouldn't attempt to modify the value it's given unless it's of the wrong type. So in your case, I would suggest leaving sanitizeValue out of the equation for now and don't bother implementing it until you have everything else working. If things are working until you try to implement them, try doing this: leave the existing implementation in place, but put in sleepValue/wakeupValue methods just to observe what's going back and forth. That should help to clear up ambiguity about why it might be breaking when you try to provide an implementation for them. <?php public function ___wakeupValue(Page $page, Field $field, $value) { $value = parent::___wakeupValue($page, $field, $value); echo "<pre>wakeupValue: "; var_dump($value); echo "<pre>"; return $value; } public function ___sleepValue(Page $page, Field $field, $value) { $value = parent::___sleepValue($page, $field, $value); echo "<pre>sleepValue: "; var_dump($value); echo "</pre>"; return $value; } That way you can see exactly what data is getting sent back and forth without modifying it. Once you know exactly what's getting sent around, you should be able to expand upon it. If you are dealing with a multi field table, then an array is going to be used as the native storage format, and it will have an index called 'data' that contains the primary value. But it's best to observe exactly what's there rather than me tell you since I don't know the full context of your situation. You should be able to do what you are wanting to do. Lets say that you want to have your 'id' integer that's stored in the database convert to an instance of MyClass during runtime. Here is pseudocode for what you would want to do: <?php // convert an instanceof MyClass to an integer id function sleepValue($value) { return $value->id; } // convert an integer id to a MyClass function wakeupValue($value) { return new MyClass($value); } // make sure $value is a MyClass, but don't bother with this for now... function sanitizeValue($value) { if($value instanceof MyClass) return $value; else throw new WireException("value was not a MyClass"); }
-
Formmailer, thanks for making this – it looks like you've done a very nice and complete job putting this together. I look forward to testing this out!
-
In your case, you can probably just have sanitizeValue return the value it's given (or don't override that method at all). The sanitizeValue method is just meant to sanitize a value set to a Page. The simplest example would be for an integer field. Lets say that you did this in the API: $page->some_integer_field = 123; When you do that, what happens behind the scenes is that $page does this: <?php $field = wire('fields')->get('some_integer_field'); $fieldtype = $field->type; $value = $fieldtype->sanitizeValue(123); // or whatever value you set $this->set('some_integer_field', $value); So your sanitizeValue method gets called every time a value is set to the page for any known field. In the case of FieldtypeInteger, it would just need to ensure that the value is in fact an integer. So FieldtypeInteger's sanitizeValue() implementation would look like this: <?php $value = (int) $value; // typecast to an integer return $value; That sanitizeValue method just needs to sanitize and convert it to whatever the expected format is. Implementation of this method is not crucial, so this is something you can come back to. This is different from sleepValue and wakeupValue because those two are for converting data to and from the format it should be in the database. For something like an integer (like above) sleepValue and wakeupValue wouldn't need to do anything at all, since an integer will be represented the same way in the DB as in the $page. But more complex things that take values from the DB and convert it to/from an object are more the type of thing where sleepValue/wakeupValue come into play. I'm very happy to have you experimenting with it. This is also helpful to me as I move towards making more official documentation and tutorials for creating this stuff. Definitely!
-
That's correct. wakeupValue is where you take whatever value is stored in the DB, and expand that to be how you want the value represented at runtime. So in your case, it sounds like you are doing it right if you are taking that ID and then building a an object from it with other data. sleepValue does the opposite of wakeupValue. It will be given the value you created with wakeupValue, and your sleepValue needs to take that and reduce it back to its representation in the DB. In your case, it sounds like that is just the ID number.
-
Those DatabaseQuery classes were mostly designed around the needs of the PageFinder, so I'm not sure how much utility it would really have outside of that. Personally, I don't like abstracting on top of DB queries (ActiveRecord and the like) but this was one case where multiple classes had to work on the same query, so it would have been dumb to do it any other way – that's where those DatabaseQuery classes came from. If you find them useful for something else, that's great, but these aren't meant as a real framework DB/query wrapper, so you are likely to come across limitations if you want to stretch them. But if you want to use them, then extend the class and override the fuel() function to point 'db' to your own. If there is more demand to provide a real framework DB query wrapper, we can add a setDb() method or something like that (after expanding the utility of the classes). But because these classes are just built for the internal needs of PW, I would look at including something like CodeIgniter's ActiveRecord if you are needing a full blown DB query wrapper.
-
I agree, I don't think Safari on the iPhone lets you do that (I've tried on a few occasions). Though not sure why not, sure seems like it should.
-
This is just using the MarkupLoadRSS module and pulling from SMF's RSS feed.
-
rootPath appears in URL structure on live server
ryan replied to domwilliams's topic in General Support
Thanks Dom, let me know what you find. If it's still doing that on a stock installation, and you don't mind giving me temporary SSH or FTP access, I expect I should be able to find a solution quickly. Though we'll find what's going on either way. -
Uploaded images not appearing in PW admin or public site
ryan replied to MarcC's topic in General Support
Great, glad you got it figured out. I was stumped for the moment -
Uploaded images not appearing in PW admin or public site
ryan replied to MarcC's topic in General Support
Can you confirm that the URL is correct, like when it shows the ? on the front end? Are you able to view files/images from any pages? Or does this universally affect all file-based assets on your site? -
You can edit it in Setup > Fields
-
rootPath appears in URL structure on live server
ryan replied to domwilliams's topic in General Support
I got your PM and tried out the site. Definitely something strange going on, because all those URLs with the server path in it should be resulting in 404s, yet they aren't. Do you have any other modules installed other than the default ones that come with PW? Would you mind installing a new/stock copy of PW in another directory on the server, just to see if it behaves in the same manner? That will at least tell us whether we need to look more at the server and your site profile, or if we have new situation that is triggering a yet unknown bug in the core. -
rootPath appears in URL structure on live server
ryan replied to domwilliams's topic in General Support
Those are the expected values there. That makes it more of a mystery because it looks like ProcessWire isn't having any issues getting the proper values from your server (there's no issue with the server environment). What you are seeing in your output is the value of $config->paths->root rather than $config->urls->root. My best guess is that something, somewhere is setting $config->urls = $config->paths (or at least, $config->urls->root = $config->paths->root). Since we haven't seen this elsewhere before, I'm wondering if there might be something in your site that's reassigning that $config var, perhaps a module. One way to test is to install a new stock installation somewhere else on the same server and see if it produces the same result. If it doesn't, then we have to look at what's different with your site. Also, I'm assuming that this breaks all of the links. If it was substituting the server's disk path for the URL, then everything would lead to a 404. But just want to confirm? If the links aren't broken, then we're very likely dealing with some server or browser "feature" that is trying to translate URLs to paths... but I've not heard of such a thing. -
Planning a page version/history module - making PageFinder hookable
ryan replied to Rob's topic in Modules/Plugins
But is having past versions of pages query-able in that manner very useful? I'm sure there are uses, but I couldn't think of any situation where I would need it to be (outside of page_id and timestamp). I think of past revisions as archives kind of like a Time Machine backup on my Mac. The main value is just in having the archives. The data is no longer current and won't ever be queried for anything other than page_id or date. At least, that's my outlook on it. But I'm sure the same could be said the other way around. It's just a matter of where you want to make the compromise. I think having selective versions of pages like you mentioned is a good compromise. This is something that I think may be best to implement in the core ProcessPageEdit module. Right now I don't think the hooks are there to do it without having a module come in and create a clone and modify the POST 'id' var before ProcessPageEdit init() is called. Though I suppose you could hook in before Pages::save, see if there is a $_POST['save_draft'] var set (or something like that), clone, then substitute in your new draft version. There are options, but it's not as straightforward as I'd like. It would probably be a frustrating first module to build. I think this capability belongs in the core, and it will be straightforward to implement there. But if you want to try building the capability, I'd recommend working in the core module: ProcessPageEdit. You can always save it out as another module and just change the Process being used by the /processwire/page/edit/ page in the system. -
I'm using the default theme for a site as well. I started out just building the site and planned to build out the features and then design everything (I like to design with known output). It didn't work out that way... the client decided that the default theme was what they wanted, so it stuck. I explained that it was hardly original and used on processwire.com, etc., but I guess if the shoe fits wear it. The lesson for me is that if I'm building out a prototype then I need to do it with no design/stylesheets so that there's no possibility the client decides they want to skip the design phase.
-
Nice job putting together this site in PW ljones, thanks for posting!
-
Module: Languages (multi language content management)
ryan replied to Oliver's topic in Modules/Plugins
If you were changing the value of $config->http404PageID, then you'd need to do it before ProcessPageView::pageNotFound. As you mentioned, Page::render just isn't useful in this case. A good place would be in your module's init() since init() is called before the $page is determined. You could also do it in a before hook to pageNotFound, but I don't think you've got any more useful information at that point than you do in init(). This is unrelated to the above, but Module::ready() is a good replacement for Page::render in many cases. It was recently added to the Module interface as an optional function, and it works very much like Module::init() but is called after the $page is determined rather than before. To use, add a ready() function to your module, and PW will automatically call that function when the $page is determined and available in the API, but before it is rendered. As a result, it is a good replacement for before(Page::render), and doesn't require a hook. But note that neither Page::render or Module::ready is going to be useful for handling 404s. -
Planning a page version/history module - making PageFinder hookable
ryan replied to Rob's topic in Modules/Plugins
I think that using pages in the system to maintain versions does simplify a lot of things, but it might be tricky and limited in others. If you are literally saving a version on every save, then you could end up with quite a large site tree and tables of data (whether visible or not). All the data in the tree is setup to be optimized for fast selection and searches. Everything is indexed. Past versions of pages don't really need that. So you end up with adding unnecessary overhead to the live tree. I am shy about the idea of having hundreds of thousands of pages in the system that don't contribute to the live site's data ... kind of like keeping all my past work projects on my desktop. But if you are in control of when you want to create a new revision (so that you don't end up with dozens-hundreds for each page) then the overhead might be a good price to pay for that capability. In fact, if you are using versions in a controlled and careful manner like this, then pages would probably be a good way to go. But if you are automatically creating a new page every time someone hits save, then I would be worried about the scalability of that. Either way, I like the way you are thinking about this and I think your ideas here have a lot of merit. The approach I took in the revisions module in development was to make a version on every page save() but just keep it JSON encoded in a flat table or files. I figured this is archived data and didn't need to be indexed in the DB. It prepares the array of data by calling each field's $field->type->sleepValue() function, which reduces the data for that page's field down to a format that can be stored anywhere. The big challenge is how to handle fieldtypes that involve files. I haven't solved that one yet. If you use pages to create your versions, you won't have to worry about that because PW's clone() function will take care of it for you. I wouldn't worry about things like users, roles, admin pages, etc. Instead, I would just suggest letting your module have a configuration option where one could check boxes next to all the templates they want to maintain versions for. -
I wasn't aware of this, just added to issues list. Thanks, Ryan
-
I think that we do want to add module dependencies. It was always the plan, but I left it out just because it originally wasn't really necessary. Now that we're getting a lot of modules, it's time to finish it and add a 'requires' option to the getModuleInfo() where it can specify an array or CSV string of modules it requires. This will be used by the system when installing/uninstalling to check and see if it's okay to install and/or uninstall.
-
Module: Languages (multi language content management)
ryan replied to Oliver's topic in Modules/Plugins
I'm not sure why that wouldn't be working either. It looks correct to me. I was originally wondering if there might be some condition where the 404 was getting thrown before your module was init()'d, but looking in the source I now see that's very unlikely. However, it is feasible if there is another 3rd party module involved that's getting init()'d and throwing it before your module is init()'d. Nico, can you describe more details about how to reproduce the case you are getting? For instance, when debugging this stuff, I think it's best to start with a stock installation with the latest source, that doesn't have any other 3rd party modules installed. That way we can remove any other factors that may be accounting for the different behavior. Then make sure it can be reproduced there. If it can be, then check to see if there are any other factors that might help Oliver reproduce it (like URL in address bar, etc.) Oliver, you may already be aware of this. But if you hook in before (rather than after) ProcessPageView::pageNotFound, you could change the value of $this->config->http404PageID to whatever Page ID you wanted. Of course, you could do that anytime before (like in your init) as well. Not sure if this is helpful in this case or not but just wanted to mention it. -
Planning a page version/history module - making PageFinder hookable
ryan replied to Rob's topic in Modules/Plugins
Sinnut is right that there is already a revisions/history module in the works. It is already somewhat functional, but I've set it aside till version 2.3 as multi language support is the focus of 2.2. The edit/preview/publish workflow is already in PW to some extent, but you can only preview when something is unpublished. Once published, you no longer have a preview. We're going to be enabling that functionality by management of separate draft and published versions of a page, and it will technically be a separate component than the revisions/history module. Behind the scenes, it will work by making an unpublished clone of the original page that overwrites the published page only when you hit 'publish'. There actually isn't anything more to it than prepending the 3 underscores. PW takes care of the rest internally. But you do have to use some care in determining which functions should be hookable. When you make a method hookable, you are telling ProcessWire to handle the function call rather than PHP (and the fast low level C code that PHP is written in). So there is more overhead in calling a hookable method than with a native PHP one (regardless of whether any hooks are attached). Methods that are called hundreds or thousands of times aren't great candidates to be hookable because it may slow execution. You mentioned a desire to make something in PageFinder hookable. Which method? I can take a look and it and see if it's a good candidate for hooks and if so I can just make it hookable in the core. Also let me know what you are trying to achieve with the hook, as I may be able to suggest alternatives too. -
Just realized that TinyMCE doesn't exactly maintain paragraph-to-line relationships very well, so there was a good chance that previous regexp wasn't going to work. Also realized there really isn't any reason for us to have a "youtube:" tag, when instead the "https://www.youtube.com" could be the tag we look for. Let me know if this version works? if(strpos($page->body, '<p>https://www.youtube.com') !== false) { $replacement = '<object width="420" height="315"><param name="movie" value="$1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="$1" type="application/x-shockwave-flash" width="420" height="315" allowscriptaccess="always" allowfullscreen="true"></embed></object>'; $page->body = preg_replace('{<p>(http://[^\s<]+)\s*</p>}', $replacement, $page->body); } echo $page->body; Bow you can just past the youtube URL in it's own paragraph (skip the "youtube:") and that's all you need to do, i.e. https://www.youtube.com/watch?v=rEKDj1OOkhI
-
I agree with Adam that I think it might be best to explain to them what a URL name is. A page's name in the URL is an important part of it, so it's not something you'd want them to ignore. But you will have an easy way to change it with the new LanguageSupport in 2.2. You can change just about anything. For instance, you could change the English translation of URL name to be something this particular user might prefer.