Jump to content

ryan

Administrators
  • Posts

    17,090
  • Joined

  • Days Won

    1,638

Everything posted by ryan

  1. $page->render() isn't listed in the Page API right now because I've not used it much beyond rendering the requested page (one page per request). But it should also be fine to call from your own code, and should be able to render as many pages as you want it to in one request. I will be adding this to the API in the future once tested in more contexts, so it's not going anywhere. It's not been tested much in the context you are asking about, so please let me know if you run into any issues with it, and we should be able to resolve them quickly. If you view the PHP source (/wire/core/Page.php), you won't find the render() method in the Page class because it's added by a module (/wire/modules/PageRender.module). There aren't any arguments to this function, so nothing to it other than calling $page->render(). This render method is available on all Page instances (like the pages returned from a find() for example). If you are rendering pages in this manner, and the templates used by those pages are defining functions or classes (whether in your template or by including them from another file), PHP may throw a fatal error about duplicate definitions. As a result, your template files should include files that have function/class definitions in them with include_once() or require_once() rather than include() or require(). If functions are defined directly in the template file (as opposed to include files), you'll want to use PHP's function_exists() function to check if your function already exists before defining it again. For regular header/footer includes, you would want to continuing using include() or require() since you want them rendered on every page you call the render() method for. It's only the ones where you are defining functions/class that you have to consider. Many people don't make their own functions and classes, so it may not be a consideration at all, but I just wanted to mention it.
  2. Your code looks right to me, as do the steps you mentioned. When you say it's not working, can you describe more? Do you ever see the form that it outputs? Or is it just that you never get an email? I'm not clear about where it stops working. I also suggest editing /site/config.php and temporarily setting $config->debug = true (near the bottom of the file). That will ensure that you see error messages during development. Also, if you have a URL where I can see it in the context of the rest of the page, that may help (and feel feel to PM it to me if you prefer not to post here).
  3. It sounds like there must be a bug somewhere if the table was incorrect in the first place. That helps to know that the rebuild fixed it. The only place this table gets populated is in the Pages::saveParents() private function, and that function is only called by the Pages::save() in certain conditions. Meaning, if there's a bug, it's probably confined to the logic in a few lines of code, which should make it relatively easy to fix. The only thing that makes it difficult is that this has not turned up before, so it may be something that only occurs under rare conditions. I'm going to take a closer look at this and see what I can find. If you encounter the Page::find() producing incorrect results again, please let me know, and I'm going to try and duplicate here too. Thanks, Ryan
  4. Those two should return the same thing, except that the first example wouldn't include the homepage (if that was part of your results). I'm testing the same thing locally, but getting the expected result -- same pages are returned from both. Hard to tell what might be the problem. What are the results from the second call? Getting different results from the get("/")->find(...) could mean something is amiss in the pages_parents table and point to a bug somewhere. PW manages this pages_parents table as a way to execute finds within a specific part of the tree. To test if there might be a problem with the table, you can force PW to rebuild it by doing this trick: $home = $pages->get("/"); $home->trackChange('template'); $home->forceSaveParents = true; $home->save(); Then try the two find operations again. Is there any change?
  5. If the above doesn't fix it, this might: Get rid of the beforePageRender hook that sets the template filename, and move it into your init() function: $template = $this->templates->get("adminbar"); if($template) $template->filename = $this->config->paths->AdminBar . "templates/sitemap.php"; I think this would work in either version of PW, though have not tested. The reason I think this might fix it is because this would set the template's filename much earlier than it currently does (well before PW would have any opportunities to check whether the sitemap page is viewable). So theoretically, this should prevent it from deciding that the page isn't viewable due to lack of a template file.
  6. I'm thinking the problem might be in wire/core/Template.php. It caches the state of whether the template filename exists. But it wasn't resetting it when the value of filename was changed. PW will only display a 404 for a page that exists to the superuser when there is no template to render the page. AdminBar appears to be setting the filename, but PW still thinks it doesn't exist because the previous "non existing" value was cached. I'm thinking this is it anyway. If you grab the latest /wire/core/Template.php from the PW 2.1 source, does this make a difference? I will also test locally later today, but wanted to get this posted before a call, hoping this was it. Thanks, Ryan
  7. You could do this in the same way as described in the other message, and give each partner their own role. But if you are dealing with just one user account per page, and the editing needs are simple, I'm not sure I would even bother with giving them admin access or any built-in page editing permission. Instead, do your own access control in your site's template. Give them their own role "partner", but with nothing but page-view access. Then some code like this in your "partner" template would be enough to determine if they can edit the content that's on their own page: <?php // if user is a partner and user and page have the same name, we'll let them edit it if($user->name == $page->name && $user->hasRole('partner')) { if($input->post->submit) { $page->setOutputFormatting(false); $page->content = $input->post->content; $page->save('content'); $page->setOutputFormatting(true); } // edit content echo "<form action='./' method='post'>"; echo "<textarea name='content'>{$page->content}</textarea>"; echo "<input type='submit' name='submit' value='Save' />"; echo "</form>"; } // display content for everyone echo "<div id='content'>{$page->content}</div>"; The example above assumes the field "content" is a textarea field that has at least the "HTML entities" formatter applied to it in the field settings. I think this is simpler then giving them admin access for such a specific need. But if you were dealing with lots of fields and of lots of types, then using the ProcessPageEdit does become a more compelling solution.
  8. This is one area where there are significant differences between PW 2.0 and 2.1, though both versions use a role-based access control system (RBAC). Here's how you do it in either version: 1. Create client role and assign permissions The first thing you'll want to do is create a role for your client, called "client".These are the permissions you'd assign to your "client" role in 2.0: ProcessPageView ProcessPageEdit ProcessPage... (any other Page permissions that you want them to have) ProcessHome* ProcessList* ProcessLogin* ProcessLogout* The permissions listed above with an asterisk (*) are assumed in 2.1, so you don't have to specify them in 2.1. These are the permissions you would assign to the "client" role in 2.1: page-view page-edit page-* (any other "page-" permissions that you want them to have) 2. Create users and give them the client role Now you have a role called "client" and it has most page editing permissions. Next you have to assign that role to some users. So you should create new users for your clients (or use existing users) and add the "client" role to them. 3. Assign the client role to the pages they can edit You've got the "client" role and users added to that role. But those users still can't edit any pages. In order to give them edit access, you have to assign the "client" role to the pages the client can edit. On a large site this isn't practical on a page-by-page basis, so you will likely want to assign roles in a manner that affects multiple pages. This is the area where PW 2.0 and 2.1 differ the most. 3a. Assigning roles to pages in ProcessWire 2.0 In PW 2.0 you assign a role to a page, and any children inherit that role setting. That role inherits down through the tree to children, grandchildren, great-grandchildren, and so on. You can also remove that added role from any of those children (grandchildren, etc.) and that will likewise be inherited in the same way. This resembles how permissions inherit on a file system through a directory structure. In the case of your /news/ page, you would want to go ahead and edit that page and add the "client" role to it (on the page's settings tab). The client can now edit the /news/ page and any children. Note that you may not necessarily want them to be able to edit the actual /news/ page (as opposed to it's children)... unfortunately that's not an option in 2.0 unless you want to add roles to the news-items on a page-by-page basis. 3b. Assigning roles to pages in ProcessWire 2.1 In PW 2.1, you no longer assign roles to individual pages. Instead you assign them to templates. So you will want to assign the "client" role to your "news-item" template. If you also want them to be able to edit the actual "news" page, you can add the "client" role to your "news" template. But I'm guessing you only want them to be able to edit the news items, and not the actual news page. Assuming you added the "client" role to just your "news-item" template, the client can now edit any news item pages. In either of the above cases, the client can't edit anything other than what you assigned to them. That client can edit "news-items" (and possibly the /news/ page), but they can't edit anything else in the site. 4. Hiding pages from the client role If you want a page to be completely hidden from your client, they have to lack view access to it. In your case, I'm assuming we're talking about a branch to hold special types of data (banners, etc.) that isn't typically rendered as pages. Lets say these pages are located under /tools/, and you want that section to be invisible to anyone except the superuser. In PW 2.0, you'd remove ALL roles from the "/tools/" page. In PW 2.1, you'd remove ALL roles from any of the templates used by pages in the "/tools/" tree of pages. If you still had some roles that you wanted these pages to be visible (like an "editor" role, or the like), then you would keep that role assigned, but remove all the others. Now only the superuser can see those pages, and the client won't see them in the admin. You can still pull data from these pages via the API as much as you'd like. 4a. Letting roles inherit in 2.1 PW 2.1 also gives you the option of having roles inherit through pages (like they do in 2.0), which you might want to do if pages in your /tools/ section are using various different templates. In that case, you'd set those various templates to "not manage access" (under each template's "access" tab). And you'd remove all roles from whatever template is being used by your main /tools/ page (we'll assume it's called your "tools" template). Now all access to your /tools/ pages is managed in one spot. 4b. Tell PW 2.1 to automatically exclude pages from search results If you are using PW 2.1, you might also want to check the box for the setting on the "tools" template that tells it to exclude pages from search results when the user doesn't have access to them. That way you won't have to worry about any of those pages showing up in any search engines you build for your site. (You couldn't do this in 2.0, instead you had to filter these yourself). Automatically excluded pages and the API Pages that a user doesn't have access to, and that are excluded from search results (as outlined above) are automatically excluded from $pages->find, $page->children and any API call that returns multiple pages. From the perspective of your API call, this is identical to the behavior of pages that have a "hidden" status. This is desirable for most of your site, but maybe not when you are trying to pull multiple banners from /tools/banners/ with a $pages->find. You can cancel that behavior for your API call by adding a "check_access=0" selector to your API call, i.e. $banners = $pages->find("parent=/tools/banners/, limit=3, sort=random, check_access=0"); That "check_access=0" essentially tells it to ignore whatever access the current user has. You don't need to do this with API calls that return single pages (like $pages->get) because such filtering is more of an annoyance than a help on such specific calls. It also maintains consistency with the behavior of pages with a "hidden" status -- they are automatically excluded API functions that return multiple pages, but not those that return single pages.
  9. Almonk posted a great article on his approach to building multi-lingual sites with ProcessWire: http://codeordie.posterous.com/multi-lingual-sites-with-the-processwire-cms
  10. I'm not at a place where I can look in the code right now, so I'm going to go back and do that later. But initially I'm thinking that Apache took over this request: /ot/processwire/&modal=1 ... because there is no "?" in the URL So it's not a valid URL, at least not one that PW will get. Do you know if PW or AdminBar generated that URL? I'm guessing PW since AdminBar works in 2.0, but just wanted to check if you knew. The error message you posted was from Apache rather than PW, because PW excludes itself from getting URLs it doesn't understand via it's htaccess file. Also in 2.1, $pages->find() and $pages->children(), etc. exclude pages that you don't have access as an option in each template's settings. You can reverse that behavior in a selector by adding: "check_access=0" to the selector. I don't think that's the case here, but just wanted to mention this option.
  11. It's probably a good way to show people how selectors are used. And someone could just copy/paste the resulting selector and use it in their own code if they wanted to. It used to be that it only showed the selector when in debug or advanced mode (like in 2.0), but since selectors are such a common thing in PW, it probably makes sense to show them all the time. I agree with you. The quick links are great though. We have to think of where they should go. Perhaps they should stay where they are (but configurable with the module), or perhaps they should be built into an admin theme? Seeing the most recently edited/added pages like you had is particularly useful. I agree, this will be a good addition. I will plan to convert them to asmSelects (or some other multi selection widget) where applicable. Thanks, Ryan
  12. Almonk--thanks for the update!
  13. Nice job. Just tested this and looked at the code. This is very well put together! I also like how you made it configurable. Also, I tested and it works equally well in 2.0 and 2.1. Your module is so nicely coded that I have one suggested optimization to make it even better. That would be to add more conditions before adding hooks. This is so that your hooks don't get added when they aren't applicable, like on the public side of the site, or when a user isn't logged in. Your module already accounts for that, but only after the hooks have already been put in place. Page::loaded can be an expensive hook (it gets called for every single page loaded in memory in the request, which could feasibly be hundreds of calls). So it's desirable to be selective about when you add a hook to it, as you can save some CPU cycles by not adding that hook when you don't need it. The init() function can't tell anything about the current $page simply because modules are init'd before PW even tries to handle the page request. So a good strategy is to have your init() just determine if your hooks will possibly be useful to the current user. If it's a guest user, there's no point in even adding hooks. But if it's not a guest user, then your hooks may be useful, depending on what the current $page->process is. Since we can't tell anything about the $page yet from init(), just delay the decision till Page::render, like this: <?php public function init() { // if there is no logged-in user, don't bother continuing if($this->user->isGuest()) return; // if the user is logged in, add a hook before Page::render // which will determine whether to add more hooks $this->addHookBefore('Page::render', $this, 'pageRender'); } public function pageRender(HookEvent $event) { // modules are init()'d before the page is loaded // so we couldn't check the value of page->process from init() // that's why we're doing it here instead. // this checks to make sure that we are in the admin and on a Process we wish to hook if(in_array((string) $this->page->process, array('ProcessPageEdit', 'ProcessTemplateEdit', 'ProcessField'))) { // hook before a redirect occurs, so we can modify the redirect URL: $this->session->addHookBefore('redirect', $this, 'sessionRedirect'); if($this->page->process == 'ProcessPageEdit') { // hook after the page has been loaded and modify the breadcrumbs array $this->session->addHookAfter('Page::loaded', $this, 'breadcrumbsEdit'); } } }
  14. Thanks, I have updated my source trees to have the same update as yours, and will push to GitHub tomorrow. And thanks for the feedback on ProcessWire, glad you are finding it useful--at least, now that we can get it to create pages. Ryan
  15. Btw, if we find that swapping the order of translit//ignore doesn't do it, then I'm going to modify the source to ignore the return value if it's blank, and instead use the value pre-iconv instead. That way it should ignore the iconv() on systems where it fails, but continue to use it where it doesn't. This is the first instance I've seen where it fails, but what turns up once it bound to turn up again. So while this sounds like a rare problem, I doubt it's unique to your server.
  16. Thanks for testing that. It looks like the iconv() is the culprit then. The strange thing is that I just compared my phpinfo() to yours, and our iconv() versions and settings are identical. Looking on php.net, it sounds like some people are reporting strangeness with iconv when combined with "//TRANSLIT//IGNORE" in some rare instances. But they were able to solve it by swapping the order to "//IGNORE//TRANSLIT". Do you want to try that? Replace: $value = iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", $value); With this: $value = iconv("UTF-8", "ASCII//IGNORE//TRANSLIT", $value); If that doesn't do it, then then you can remove that line entirely. It's only there to provide better translation of accented characters and such, and it's not required. If you take it out, it'll just replace unknown characters with dashes rather than trying to translate from UTF-8 to ASCII.
  17. That's interesting. So it sounds like it's failing in the Page::set() method. In this part near the top: case 'name': if($this->isLoaded) { $beautify = empty($this->settings[$key]); $value = $this->fuel('sanitizer')->pageName($value, $beautify); if($this->settings[$key] !== $value) $this->trackChange($key); } $this->settings[$key] = $value; break; Following the path of calls, Sanitizer::pageName() is the next place to look. It's in the file /wire/core/Sanitizer.php. I've got my eye on these lines: if($beautify) { $value = iconv("UTF-8", "ASCII//TRANSLIT//IGNORE", $value); } $value = strtolower($this->nameFilter($value, array('-', '_', '.'), '-')); Do you want to try removing or commenting out those lines and seeing if it makes any difference? I'm especially wondering about the iconv(), and if it might be returning something different on your server.
  18. Was the die($this->page->name) placed after this line? $this->page->name = $name; For example, I'm wondering what this would do: $this->page = new Page($template); // existing lines $this->page->parent = $this->parent; $this->page->name = $name; var_dump($this->page->name); die(); // add this line right after the above Trying to determine if $this->page->name is "0" after specifically setting it.
  19. I got a look at your phpinfo and nothing jumps out as a known problem (versions look good, etc.). It's a mystery so far. I've seen this problem when the PHP version was less than 5.2.4, and that's one of the reasons why that's the minimum version required by PW. But you are running 5.2.17, so no problem there. If you want to set me up with a temporary PW superuser login and FTP, I will be glad to go in and find where exactly the problem is. My email is ryan at the domain name of this site. Or if you prefer, I can tell you how to debug it yourself. We should be able to find out where it's happening relatively easily since it's apparently either in ProcessPageAdd::processInput() or Pages::save(). So it's just a matter of inserting: "die($page->name);" until we find the location where it's changing from the actual name to "0", and there aren't many lines of code to test here. I'm confident we'll be able to find a fix.
  20. The field names look fine. In the past there have been a couple of reserved words that I'd forgotten to reserve in the system, so just wanted to make sure we weren't running into something like that. I will keep an eye out for your phpinfo and then reply here as soon as I get a look at it.
  21. Can you PM or email me a link to your phpinfo? I want to get a look at your PHP and MySQL version. This would be a URL to a file like "test.php" that contains nothing but this: <?php phpinfo(); Or if you know the versions already, post in here. If your versions are good, one thing you may want to try is to download a new copy of PW and replace the /wire/ directory with the one from the new copy. Just in case there is a corrupted file or something off in that commit, that will at least correct it. If that doesn't do it, you may want to look at running a database repair. If you have access to PhpMyAdmin, view the database being used by PW and "check all" the tables, and select "repair" in the select box at the bottom. If neither of those do the trick, can you post list of your field names and template names?
  22. That is definitely strange. There is no connection between the page ID and page name, so it's particularly odd that your name field is getting populated with the ID. It almost sounds to me like the browser is mixing up the fields. What browser are you using? Also what version of ProcessWire is this? (2.0 or 2.1) and how recently did you download it? Do you have any 3rd party modules installed? You mentioned that it developed this issue. Does that mean that it wasn't doing it, and then it started recently? If so, can you think of anything that changed, whether in your PW install, the server, or the browser you are using to access it?
  23. Arkster, Welcome to the forums and thank you for your feedback! Ryan
  24. Antti, thanks for the update! I have merged into the source, great ideas and updates. The module is still a work in progress and I agree it's showing too many options in the state before you updated it, so this is a welcome change. We may want to go even further, and not show any sidebar at all unless they clicked a "show more options" or "advanced search" link somewhere (perhaps under or above the search results). This is for reasons that are related to the paragraph below... Regarding the 'another way to browse', that's a good point. Wanted to get all these search options as GET vars so that other modules could link to specific things. For instance, when viewing what roles are assigned to a template, each role would be linked to a search of: "template=user, role=$role" so that you could then get a list of all users that have access to pages using a template. That's just one example of many that we could already start using in the admin. But in this use, I'm thinking it's maybe better to hide any other search options behind an 'advanced' link. In part because many users may not even think of this as a traditional search since it doesn't involve searching for any text. And less options may help it to feel more integrated with the context of where they clicked from. What do you think? One of the next steps for this module is also giving it the ability to output results in JSON, for ajax use. Thanks, Ryan
  25. Just updated the 2.1 development source code on GitHub with a new admin search module. This one is a major improvement over the existing admin search module (the existing one was very basic). This should also be compatible with 2.0, so I'm going to be adding it to the stable 2.0 branch after a little more testing. Here is a screenshot attached below that demonstrates what's new in this module.
×
×
  • Create New...