-
Posts
17,094 -
Joined
-
Days Won
1,639
Everything posted by ryan
-
No problem, I'm actually glad to see it in action on that site because it's a great test case of the new permission. I like your 'Desktop' option of you've added in the admin too. And as always, your theme is looking great. Let me know when you are ready to make a 2.2 version of it and I can tell you what to add.
-
You could hard code that check in your nav output and just say something like: when the page ID is 123, pull in this other nav and display it. If it's something that is going to remain relatively static, that's what I'd do. If not static, you could use a checkbox field instead. But here's an example of how you might do it statically: <?php function menuTree(PageArray $children) { echo "<ul>"; foreach($children as $child) { echo "<li><a href='{$child->url}'>{$child->title}</a>"; // below, 123, 456, 789 are IDs of pages where duplicate nav should appear if(in_array($child->id, array(123, 456, 789)) { // below, 321 is ID of page having the children you want to duplicate $out .= menuTree(wire('pages')->get(321)->children); } else if($child->numChildren) { $out .= menuTree($child->children); } $out .= "</li>"; } $out .= "</ul>"; return $out; } echo menuTree($pages->get("/")->children);
-
I just logged in and looked at your installation. The problem here is that you aren't actually using the page-create permission anywhere. I went through all the templates allowed as children on the 'language_tree' template, and none of them have 'Create Pages' checked for the editor role. As a result, even though editor has page-add permission on language_tree, they didn't have page-create permission on any of the templates allowed there. So editor couldn't add any pages below de-de (language_tree). I went in and checked the page-create permission for one of the allowed templates 'ressort-page'. Once I did that, the 'new' link started showing up under de-de. So unless I'm misunderstanding what you are saying, I think it's working correctly, but you just need to check a few boxes. I restored the ressort-page template back to how it was and removed the page-create permission there. But try adding it to one or more of those allowed templates to see what I mean.
-
Can you check that the editor role has page-create permission on at least one template? And by that, I mean at least one template that is allowed in the place where you've given them the page-add permission? Since page-create was just added in, non-superuser roles aren't going to have that permission assigned anywhere at first. Another thing to consider is family settings, which can affect permission. For instance, if they have page-create permission for template A and page-add permission on template B, then they should be able to create pages of type A as children of type B. However, [in the 'family' tab] if template A only allows template C as a parent, or template B only allows children of type D, then that restriction will prevent them from getting the permission. I'm not sure that I can tell much from using the editor login, because all the relevant settings are accessible to superuser only. Though if you find it's still not working how it should, it would be good for me to duplicate it with a simple test case here so that I can more easily fix it. I'm not sure if it matters to the function of that module, but just wanted to mention that "return true;" in an event function technically does nothing. The return value is not used for anything. In order to return something from the hooked function, you'd need to populate $event->return = true; --- Edit: found that you did send me a superuser account in PM. Sorry, missed that before. Trying that...
-
Soma, does the 'new' show up where it should if you comment out the Page::addable hook? I'm just wondering if we need to look in the module you posted or in PW newly added code. Also, this could potentially be the problem: if($this->user->editable_pages->has($p)) return true; You should do this instead: if($this->user->editable_pages->has($p)) { $event->return = true; return; } or if you want to keep it on one line: if($this->user->editable_pages->has($p)) return ($event->return = true);
-
Soma, I plugged this into the dev branch yesterday so you should now have page-create permission back in the system, controlled on a per-template basis. Would you mind testing this when you have a moment? I wasn't sure exactly how to duplicate your access control scenario. I left off the page-delete for now because deleting pages is a bit more of a complex question: "delete any pages of this type, or just pages the user created", and we'll answer that question with a separate permission or add a separate auto-assigned owner role.
-
custom login from modal box, redirect after login failure
ryan replied to AnotherAndrew's topic in API & Templates
I'm not sure if it's the best way to go, but you could just combine what you are already doing into two steps. Have the form submit without the _parent target so that it stays in fancybox. But if login is a success, then use that auto-closing behavior that you mentioned by submitting another form to the _parent. I've not tried this, so I'm just going on trying to take advantage of the existing behavior you mentioned: <?php if($session->login($input->post->user, $input->post->pass)) { // login success if($user->isSuperuser()) $url = './'; else $url = '/members/'; $out = "<form id='success' action='$url' target='_parent' method='get'>" . "<input type='hidden' name='login' value='1' />" . "</form>" . "<script>$(document).ready(function() { $('#success').submit(); }); </script>"; // submit the form } else { // display error } Note I included that hidden form field called 'login' above in case you want your _parent frame to look for and display a "you logged in" message, or something like this: <?php if($input->get->login && $user->isLoggedin()) echo "<h2>Welcome {$user->name}!</h2>"; -
I'm not sure that I understand the context here well enough to say which is the best path to take. But if you've got trees of nav that you need to repeat in various places, then I wouldn't try to build that as a structure of redirect pages. I think your best bet is just to build that logic into your nav generation function. I've also done this kind of repetition just with jQuery since the links didn't really need to be repeated in the underlying markup. An example is http://villarental.com – it has pull down menus at the top, but if you view the source at look at the top nav UL (#topnav), you'll see there's no markup for it. Some javascript is just duplicating the links from the footer into the topnav. So if your nav repetition is for something that's for look + feel rather than accessibility, consider a little jQuery which probably provides the simplest answer.
-
Yeah I think we probably should. Here they are. I've tried to tailor them for cheatsheet format and included an @advanced tag where applicable. I understand the sentences of text don't fit in the cheatsheet, so wasn't sure how you'd want to handle those (or leave them out), but put them here in case helpful. FieldtypeFile or FieldtypeImage can be configured to hold a single file or multiple files. When configured to hold multiple files, it is a WireArray (called Pagefiles or Pageimages) with these additions: <?php $files->path; // Returns the full server disk path where files are stored $files->url; // Returns the URL where files are stored $files->page; // Returns the $page that contains this set of files $files->delete($file); // Removes the file and deletes from disk when page is saved (alias of remove) $files->deleteAll(); // Removes all items and deletes them from disk when page is saved @advanced Each item in the WireArray is a $file or $image (called Pagefile or Pageimage). Likewise, when FieldtypeFile or FieldtypeImage is configured to hold a single file, it is just the $file or $image with the following properties and methods: $file properties <?php $file->url; // URL to the file on the server $file->filename; // full disk path to the file on the server $file->name; // Returns the filename without the path (basename) $file->description; // value of the file's description field (text). Note you can set this property directly. $file->ext; // file's extension (i.e. last 3 or so characters) $file->filesize; // file size, number of bytes $file->filesizeStr; // file size as a formatted string $file->pagefiles; // the $files array that contains this file @advanced $file->page; // the $page that contains this file @advanced (string) $file; // returns the file's name (no path) $file methods <?php $file->rename($name); // Rename this file to the given name (no path). Returns true on success, false on failure. $file->getNext(); // Returns the next file in a multi-file field, or NULL if at the end @advanced $file->getPrev(); // Returns the previous file in a multi-file field, or NULL if at the beginning @advanced When dealing an $image, it is the same as a $file, but with the following additions: $image properties (in addition to those in $file): <?php $image->width; // Width of image, in pixels $image->height; // Height of image, in pixels $image->original; // Reference to original $image, if this is a resized version. @advanced $image methods (in addition to those in $file): <?php $image->size($width, $height); // Return a new $image with the given dimensions (proportional, center crop) $image->width($width); // Return a new $image with the given width (proportional height, center crop) $image->height($height); // Return a new $image with the given height (proportional width, center crop) $image->getVariations(); // Returns a WireArray (Pageimages) of all size variations of this image. @advanced $image->removeVariations(); // Deletes all size variations of this image (be careful) @advanced
-
Another option, if you want something you can reuse anytime: 1. Create a new field and call it 'redirect_url' or something like that, and use the 'URL' fieldtype. 2. Add that field to your template where you'd want to use it, or create a new template just for the purpose, like a template named 'redirect'. 3. Edit the page that you want to be a symlink and populate the 'redirect_url' field with the URL you want it to redirect to. 4. In your nav-generation code that links to the pages, do something like this: <?php $url = $subpage->get("redirect_url|url"); // use redirect_url if there, otherwise use url echo "<a href='$url'>{$subpage->title}</a>"; 5. You might also want to add this to your template that has the 'redirect_url' field: just in case there's anything linking to it directly. That way it'll send people to the right place either way: <?php if($page->redirect_url) $session->redirect($page->redirect_url);
-
Time-limited recover from trash is something that we could do for those users. That's because that user would be listed in the page as the modifiedUser. That's enough for us to assume that they at least had access to it, before it was deleted. We just need a way to determine where the page originally came from in order to restore it. But that could be as simple as encoding the original parent ID in the title field or something. So even if we don't let them go dumpster diving, at least we could let them sift through their own trash in some form or another.
-
You'd probably want to make a copy of the FieldtypeComments and modify/rename it towards your needs. You'd need to change the DB schema that it uses so that you'd have a URL field, and then update the CommentForm class to accept it and save it. Basically, I'd just duplicate everything for the 'email' field to make a URL field. When it comes to sanitizing it, you'd just use the $sanitizer->url() rather than $sanitizer->email(). URLs are kind of open-ended in terms of what characters they allow, so make sure you run it through htmlentities() before outputting anywhere at runtime.
-
The /wire/core/ImageSizer class accepts a quality setting, but the Image fieldtype doesn't use it at present, so it just defaults to a quality setting of 90 (out of 100). My experience has been that that's ideal for most cases. But this would be one good future improvement to make this configurable.
-
You've convinced me, I changed my mind on this. I'm going to add page-create and page-delete columns to that template access control list and they will just be there. We can decide if we should move any to an advanced mode/option based on community feedback, but I don't want to exclude some access control scenarios for simplicity.
-
Version requirements will definitely be part of our module dependency system.
-
How to save submitted form data from a module
ryan replied to evanmcd's topic in Module/Plugin Development
Are you sure this is from FieldtypeComments? That module doesn't override the formatValue() function. Also the comments on that function refer to renderMapMarkup? This is different than how formatValue is meant to be used, but it is still okay. But there is a major component missing, and that is how the value goes from user input into your fieldtype? Fieldtypes aren't meant to handle user input (Inputfields are), so we have to come up with another way to get front-end user input into here. Before we go further, I just mention how FieldtypeComments works: It has no formatValue() function because it doesn't need one. formatValue is an optional method to convert a runtime value into one ready for presentation on the site... the best example is taking a string of text and encoding the entities in it (i.e. '&' becomes '&'). FieldtypeComments doesn't need a formatValue() function because its wakeupValue() returns an object (of type CommentArray). That CommentArray has some built in helper methods that you can use on your site to render comments or render the form for them. So here's how you render comments: echo $page->comments->render(); And the form for inputting comments is rendered like this: echo $page->comments->renderForm(); That renderForm() method actually loads up another class called CommentForm(), and that class is looking for posted comments. This is different from other Fieldtypes because it's something designed to accept input from the frontend rather than the admin. Admin input is handled with Inputfields. So in your case, you are trying to achieve the same result at FieldtypeComments. I think it may be okay to let your formatValue() function take this role. But your formatValue function will need to detect when a up/down has been submitted, in addition to outputting the form that it is now. At least for now, I would suggest making your Fieldtype a regular Fieldtype and not a FieldtypeMulti. I don't think a FieldtypeMulti isn't necessary here and might even make it more difficult to implement. Instead, I would use a schema that increments a single counter for every up vote. Probably the same schema as FieldtypeInteger. If you wanted to maintain separate up and down counters, then you would expand your Fieldtype schema to have two counters. But I would suggest just starting with one to get things going, and then expand. Likewise, if you determine you need a FieldtypeMulti, than no problem, but since that evolves from a regular Fieldtype, it's good to understand the workings of a regular Fieldtype first. Assuming the stuff in the paragraph above, your formatValue would do something like this: <?php public function formatValue(Page $page, Field $field, $value) { if($input->post->vote) { // a vote was submitted // turns off outputFormatting so we can save a raw value $page->setOutputFormatting(false); // now increment and save the value $name = $field->name; $value++; // increment the counter $page->set($name, $value); $page->save($name); // turn outputFormatting back on, so we're leaving everything as it was $page->setOutputFormatting(true); $out = "<p>Thank you for voting. Current votes: $value</p>"; } else { // no vote submitted, display the form $out = "<form action='./' method='post'>" . "<p>Current votes: $value</p>" . "<p><input type='submit' name='vote' value='Vote' /></p>" . "</form>"; } return $out; } Note that there is no security or validation to ensure the user doesn't double vote or hasn't already voted for that page, etc. So it's just for demonstration purposes, but I think gets across the part I was talking about: something to identify the vote submission and save the vote. -
Trash is tricky because if a page inherits it's access, then that association is lost once moved to the trash. The trash is undefined in terms of access control–a no-mans land. Some pages in there may be using templates with access settings and some not. It becomes a can of worms if we let non superusers in there. We'll find a way around it down the road, but in the short term I think it's safest to lock that part down to superusers. Others experience may be different, but I've only ever had a client delete something they weren't supposed to just once, and that's over several years. But that may also be because a lot of the sites I deal with rarely need stuff to be deleted, so it doesn't come up often.
-
How to show a list of children, grouped by category title?
ryan replied to MarcC's topic in General Support
Here's another way you could do it too. Though I'd probably use Soma's more straightforward approach unless you are dealing with a large quantity of categories. The reason for that is that this approach (below) is technically a little faster since it's one samples query to cover all categories rather than one samples query per category. But I think Soma's method is easier to follow with more straightforward logic. <?php $cats = $pages->find("parent=/categories/"); $samples = $pages->find("parent=/music-samples/, category=$cats, sort=category.name, sort=name"); $last = null; foreach($samples as $s) { if($s->category !== $last) { if($last) echo "</ul>"; echo "<h2>{$s->category->title}</h2><ul>"; } echo "<li>{$s->title}</li>"; $last = $s->category; } echo "</ul>"; -
Usually you'd handle this with two roles. One role that has page-edit and page-delete permissions to be assigned to the template used by the child pages. And another role that has page-edit and page-add permissions, to be assigned to the parent's template. By "assigned" I mean, check the box for it to be "editable" to each of those roles in the template's access tab. Then you'd give the user both of those roles. But I realized after trying it myself that it wasn't quite working as intended. I committed an update to the dev branch so that it should work now. Btw, your client won't be able to actually delete anything either way. The definition of "delete" to non-superuser roles is just to move to the trash. So if you don't want to move to the PW 2.2 dev branch just yet, at least take comfort that if your client happens to delete something you don't want them to, you can always go back and undelete it.
-
Linebreaks are now supported in the field descriptions (dev branch). It just runs the description text through PHP's nl2br() before outputting it. While I was there, I also made it so that you can use markdown style links in field descriptions as well. i.e. [ProcessWire](http://processwire.com)
-
The speed of the animations seems alright here, but I think it's going to depend on what computer and browser one is using. I'm generally indifferent about animations too. They seem nice here, but I'm not experiencing a slowdown either. If they are slow for lots of people, maybe better to get rid of them or whatever Soma thinks is best. Animation or not, I just really like the functionality of being able to expand one section like this, as well as the "+" sign to do it. While I think visually it might fit nicely in the top and make closing easier, I also think it would be easier to miss at first glance. I like it at the end because it's very clear about what that "+" is for. If it were at the top of each section, people might think that it means "make sticky" or "open in new window" or something like that. Whereas at the end of the list, the placement context becomes part of the message – its hard to confuse it with anything other than "show more". But ultimately I love the functionality of it regardless of where it's placed.
-
Thanks for all of your feedback. Great ideas Maruchan! Based on our conversation here, I'm now feeling that perhaps we should test the waters first with a ready-to-go site profile. I'm going to do more thinking here over the holidays and try to identify some areas of need that might be good to pursue.
-
Nice work statestreet! Great site. I'm using some script in Firefox that makes me enable JS on a site-by-site basis, so when I first arrived the site thought JS was off. It told me: "You need Javascript to view this site. At least it's not Flash, right?" – got a good laugh out of that.
-
How to save submitted form data from a module
ryan replied to evanmcd's topic in Module/Plugin Development
Evan, I'm not sure we can tell much from the code snippet you posted. Because a Fieldtype is a system with various components involved, I think we might need to see the broader context here (full Fieldtype and Inputfield). -
The typing of "images" in a <p> was just an example of using a little template file code to automate some specific runtime output. It's not a standard or even a recommendation, just a little code snippet I found handy in a couple cases. Unless I've misunderstood, now you are asking for exactly what the built-in functionality does– Click on the photo icon in TinyMCE and add a photo. If you then want to link it to something, then click on the photo to highlight it and then click on the link icon to select what you want it to link to.