Jump to content

ryan

Administrators
  • Posts

    17,304
  • Joined

  • Days Won

    1,724

Everything posted by ryan

  1. Beautiful work!
  2. The export profile module is 2.3 compatible, but not when it comes to multi-language sites using the core LanguageSupport modules. That's something that's been on my to-do list for awhile. I just don't use the Profile Export module often enough, but hope to update that a little after 2.4 is released.
  3. Fay, I noticed your last two screenshots contain a plain HTML field with raw visible HTML tags. Is that what you intended, or is this supposed to be a rich text field? I ask because it's a little unusual to edit raw HTML like that (that's what TinyMCE and CKEditor are great for, or an LML like Markdown or Textile). Always respect for editing raw HTML, but it's not something I see very often, so just wanted to make sure there's not some JS error or something blocking the rich text editor.
  4. Template caching is language aware (and it includes the language as part of the cache file's id), but you'd have to have some aspect of the request determine the language before rendering the page. Otherwise there's no way to connect that cache file with the request. The simplest way to do that is to use the LanguageSupportPageNames module, to ensure that your homepage (for example) has a different URL for each language. If you are determining language from the hostname (i.e. en.domain.com, it.domain.com, etc.), then you'd have to have a before(Page::render) hook that sets the $user->language based on the hostname. I'm not sure what method you are using to determine language, so let me know and I can give you a better example.
  5. ProcessWire requires sessions, so it's not something you have to install. Though the database sessions module is an optional install. But $user->isLoggedin(); has to do with the current user only. It cannot tell you if other users (separate from the current session) are logged in or not.
  6. Also look into using RSS feeds (via MarkupRSS and/or MarkupLoadRSS) as these are one of the most common ways for sites to share content.
  7. These should also work (on dev): // save directly from page object $page->save(array('quiet' => true)); // save just 1 field from page object $page->save('myfield', array('quiet' => true)); When quiet mode is set, the modified date is set to whatever is specified in the page. Meaning, the modified date is not updated unless you change it yourself. Quiet mode also lets you modify the modifedUser and createdUser for the page, if you want to. These are two properties you can't usually modify, but quiet mode lets you do it.
  8. Soma, glad you found the source of the HTML document. Regarding the saveReady, I think it may be problematic to try and save a page in there because it's going recursive. Calling a save() from saveReady triggers another save and thus another saveReady, and so on. I don't yet know why its working with some hooks and not others, but wanted to point out the potential for an infinite loop there. When recursion is involved sometimes things can get weird, or at least hard to debug. If it's possible to move it all to a saved() hook, that may be less prone to issues. While there would still be recursion there, at least it wouldn't interfere with the save order. Technically what you are trying to do should be possible by preventing an infinite loop from within your hook (which I think your template check is doing), but this is one of those scenarios that may require more abstract jumps and debugging than is worth the effort, at least if you can accomplish it in any simpler fashion.
  9. Soma, I'm not sure I follow everything here and agree it all sounds pretty odd. First things first, I think it'd be good to figure out where the HTML4 document is coming from. The only thing I can guess is TinyMCE is saving it this way, and you are just discovering it as a result of this debugging session? It almost looks to me like the HTML contents of TinyMCE's iframe window. If you still don't know where this is coming from, then I think we need to focus in on that cause it seems really odd (PW does not generate any HTML documents like that). What other modules are installed and running? Is it possible it's being added by some mod_security type Apache module (automatically adding an <html> wrapper around content it sees as HTML in a POST request?)
  10. Here are some API additions to the dev branch, primarily for WireArray/PageArray/etc. I've found these very handy lately, and would have on almost any project I worked on, so decided they'd add value to the core. I'll add these to the cheatsheet once 2.4 replaces 2.3, but for now, here they are. The examples here use PageArray, but note that these API additions apply to any WireArray derived type, not just PageArray. WireArray::implode() Implode all elements to a delimiter-separated string containing the given property from each item. Similar to PHP's implode() function. Usage: $string = $items->implode([$delimiter], $property, [$options]); Arguments: $delimiter - The delimiter to separate each item by (or the glue to tie them together). May be omitted if not needed $property - The property to retrieve from each item (i.e. "title"), or a function that returns the value to store. If a function/closure is provided it is given the $item (argument 1) and the $key (argument 2), and it should return the value (string) to use. [$options] - This argument is optional. When used, it's an array with modifiers to the behavior: skipEmpty: Whether empty items should be skipped (default=true) prepend: String to prepend to result. Ignored if result is blank. append: String to prepend to result. Ignored if result is blank. Examples: $items = $pages->find("template=basic-page"); // render all the titles, each separated by a <br>, for each page in $items echo $items->implode('<br>', 'title'); // render an unordered list of each item's title echo "<ul><li>"; echo $items->implode('</li><li>', 'title'); echo "</li></ul>"; // same as above, but using prepend/append options, // this ensures no list generated when $items is empty echo $items->implode('</li><li>', 'title', array( 'prepend' => '<ul><li>', 'append' => '</li></ul>' )); // same as above, but with all items now presented as links // this demonstrates use of $property as a function. note that // we are also omitting the delimiter here as well, since we don't need it echo $items->implode(function($item) { return "<li><a href='$item->url'>$item->title</a></li>"; }, array('prepend' => '<ul>', 'append' => '</ul>')); WireArray::explode() Return a plain array of the requested property from each item. Similar to PHP's explode() function. The returned PHP array uses the same keys as the original WireArray (if that matters). Usage: $array = $items->explode($property); Arguments: $property - The name of the property (string) to have in each array element (i.e. "title"). You may also provide a function/closure here that should return the value to store. When a function/closure is used it receives the $item as the first argument and the $key (if needed) as the second. Examples: // get an array containing the 'title' of each page $array = $items->explode('title'); // get an array containing the id, url and title of each page $array = $items->explode(function($item) { return array( 'id' => $item->id, 'url' => $item->url, 'title' => $item->title ); }); WireArray::data() Store or retrieve an arbitrary/extra data value in this WireArray. This is exactly the same thing that it is jQuery. I've personally found this useful when building search engines: the search engine can store extra meta data of what was searched for as a data() property. Then any other functions receiving the WireArray/PageArray have access to this additional info. For example, the search engine portion of your site could populate an array of summary data about what was searched for, and the render/output code could render it to the user. Usage: // Setting data $items->data('key', 'value'); // Getting data $value = $items->data('key'); // Get array (indexed by key) of all data $values = $items->data(); Arguments: The above usage section explains all that's needed to know about the arguments. The only additional comments I'd make are that 'key' should always be a string, and 'value' can be anything you want it to be. Example: function findSkyscrapers() { $floors = (int) wire('input')->get->floors; $year = (int) wire('input')->get->year; $items = wire('pages')->find("template=skyscraper, floors=$floors, year=$year"); $items->data('summary', array( 'Number of floors' => $floors, 'Year constructed' => $year )); return $items; } // the render function can focus purely on output function renderSkyscrapers($items) { echo "<h2>You searched for:</h2>"; // render the summary of what was searched for foreach($items->data('summary') as $label => $value) { echo "<p>$label: $value</p>"; } echo "<h3>Skyscrapers found:</h3>"; // note use of new implode() function, though a foreach() would be just as well here echo $items->implode(function($item) { return "<p><a href='$item->url'>$item->title</a></p>"; }); } WireArray::and() WireData::and() Return a new copy of the WireArray with the given item(s) appended. Primarily as a syntax convenience for various situations. This is similar to jQuery's add() and andSelf() functions, but I've always felt "add" implied adding something to the original rather than creating a new combination, so went with "and" in this case. The term "and" is actually a reserved word in PHP, so you can't usually have a function named "and()", but through the magic of hooks, ProcessWire can. This function should reduce the instances in which you'd need to do "$a = new PageArray();" for example. Usage: // create a new WireArray with $items and $item (appended) $myItems = $items->and($item); // create a new WireArray with $items and $moreItems (appended) $myItems = $items->and($moreItems); // create a new WireArray with $items and $item (prepended) $myItems = $item->and($items); // create a new WireArray with $item and $anotherItem (appended) $myItems = $item->and($anotherItem); // create a new WireArray 4 items $family = $pappa->and($mamma)->and($brother)->and($sister); Examples: // generate breadcrumb trail that includes current page foreach($page->parents->and($page) as $item) { echo "<a href='$item->url'>$item->title</a> / "; } // check if page or its children has a featured checkbox if($page->and($page->children)->has("featured=1")) { echo "<p>Featured!</p>"; }
  11. Thanks for your message and PR. This was fixed yesterday morning as soon as I saw it. I can only guess that I was still getting an older cached version of the JS file when testing this change.
  12. Lets say you've got the page /family/ that has everything below it you want protected by a login. Create a new role (in Access > Roles), call it whatever you'd like but maybe "family" is a good name. For permissions, check the box for Page View, and that's it. Create one or more new users for your family, and give them the family role. In your admin edit the template used by your /family/ page (let's say it's also called 'family') and go to the 'Access' tab. Check the box to enable access control. For view access, check the box for "family" but not for "guest". Also when editing your family template, for the section on "what to do when a user doesn't have access", choose the box to redirect them to the login form. Or if you want your own custom login form, you can later change this to redirect to a custom URL that contains your login form. In your /site/config.php file, see the section on the "pagefileSecure" option and determine if that is something you will want to use or not. By default is is off.
  13. This is significantly more scalable and resource friendly than repeaters. It's directly connected to a single DB table without any other overhead.
  14. That usually means that 1) your roles don't permit you publish access; or 2) not all required fields are filled in.
  15. Actually either syntax should work here. The $users->add('name'); function is a valid way to create a new user. Though the $u->of(); and $u->save(); immediately after your add() aren't necessary. The $users->add() syntax is newer though, so may not be present in past versions of PW.
  16. Perhaps FieldtypeFloat could temporarily switch the locale back to C whenever it needs to operate on it, then switch it back.
  17. ryan

    CollagePlus

    Are you using CollagePlus on it's own or the CollagePlus module in ProcessWire?
  18. It sounds like you are talking about from the API side. You can work with repeaters just like any other pages, but you just have to know where to find them. Your repeater items are going to be using a template with the name of your repeater field pepended by "repeater_". So if you've got a repeater field called "slideshow", then pages within that repeater are going to be using the "repeater_slideshow" template. As a result, you can query them like this: $pages->find("template=repeater_slideshow, ..."); Repeaters are kept in the admin structure, so if your code needs to do it's thing on the front-end of your site, then you'll also want an "include=all". Note that unpublished+hidden repeaters are considered unpopulated "ready" pages, so you can safely skip over them.
  19. Actually, you can do this on the dev branch. Lets assume that cities are children of countries and that is reflected in your page structure (i.e. /countries/france/paris/). Create your 2 page fields (country and city), and configure 'country' as a single page field with "parent" set to "/countries/". Next, for the "city" field configuration, use the "Custom selector to find selectable pages", present on the "input" tab. In that field, enter "parent=page.country". Save and try it out. This works with select, selectMultiple and asmSelect fields (and possibly others), though not yet with checkboxes, radios or PageListSelect.
  20. Hard to say for sure. But those 4 unpublished records were most likely intentional 'ready' pages. This quantity is defined in your repeater field settings (details tab).
  21. I have no experience with Amazon's setup here, but definitely curious. Have you tried enabling PW's debug mode in /site/config.php just to see if maybe some errors are occurring that might be getting missed? It'd also be interesting to know if any errors show up in your JS console. I'd also be curious what versions of MySQL and PHP are in use here. If you PW login and a phpinfo(); link you can PM me I'll be happy to take a look.
  22. require_once isn't ideal for prepend/append template file settings. When you call $page->render(); you want to know that everything you expect to be included is included. A lot of us call render() methods on other pages, which a require_once() could break. If there are things that need to be require_once (like function or class definitions) you can always move those to another file and require_once them from your prependTemplateFile. My prependTemplateFile usually looks something like this: // initialize page regions with default values // this will be output eventually in _main.php $headline = $page->title; $browserTitle = $page->title; $body = $page->body; $sidebar = ''; // include shared function libraries require_once('./includes/finder.php'); require_once('./includes/render.php'); As for your particular case, it sounds like you've got some logic running after output has started. You want to move that logic to somewhere before output starts. Given that, prependTemplateFile is not an ideal place to output header markup. However, if you want to continue doing that, then you may be able to place this at the top of your prepend TemplateFile: if($page->name == 'http404') return;
  23. The unzipping in that part of ProcessWire doesn't use ZipArchive, and it needs to be updated. ZipArchive didn't used to be very common, so calling an unzip utility from the shell (what PW does) used to be more reliable across servers. Unfortunately that method doesn't work on Windows servers. Also, ZipArchive is very common now and this part of PW just needs to be updated to use it instead of the older method.
  24. Also, you ideally want to sort these before they come out of the database rather than after. That happens in your $pages->find() or $page->children() or whatever code comes before the code you posted that populates $results. i.e. $results = $pages->find("template=blog, sort=-blog_date, limit=3");
  25. You should be able to do categories with form builder in this case. But note that your 'category' field will have to be a field of type 'Page' both in your form and in your ProcessWire fields. I'm guessing that you've currently got 'category' as a regular select field (rather than Page field) in Form Builder?
×
×
  • Create New...