Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 02/23/2015 in all areas

  1. I would do it like it is written in the .htaccess file of the PW dev branch (line 104). I use this method on production sites, too, and it works smoothly.
    6 points
  2. Slight update (sorry if this is a monologue!) I was quite comfortable building out the static site in Middleman, although I did find the documentation extremely disappointing, for a seemingly well-backed product there isn't a great deal of meat beneath the gravy docs-wise. I started to consider looking at one of the paid products (Kirby / Statamic), they both seemed to be very solid, had good documentation and had the bonus of being a "full" CMS despite being NoDB. In the end I decided to go with Statamic for a few reasons. I was extremely impressed with their docs. The simple admin area is very nicely put together and pretty intuitive. So far I pretty much have the project coded up and have come across some really nice features (some that PW may learn from - as per the original post by Diogo ) Others aren't really relevant as Statamic and PW do cater to different sorts of sites. I doubt it will be used for more complicated database-driven sites, that said, what I do like about it: 1. Configuration through YAML - Have to say this is proving to be a real hit for me. Set global variables, decide which fields to show for any given template in the admin 2. Being able to add content through files - I personally haven't made a great deal of use of this yet as I still prefer adding content through an interface at this stage. Despite this I can see the appeal, especially to people who use MarkDown a lot. 3. NoDB, easier site synchronizing/backups - OK so this is an obvious one but clearly having no database is an advantage when it comes to Zipping a site up or keeping two copies in sync. 4. Templating syntax - This is controversial, not least to myself. I wholeheartedly agree with Ryan's appraisal on using PHP syntax in PW. That said, there's no arguing that when we're using a simpler system for a simpler site, there's something pleasant about being able to leave out some of the less glamorous parts of writing PHP ( ; {} [] ). My preference for tenplating engines over pure PHP completely depends on the aesthetics of the engine syntax. In Statamic's case it is elegant so a plus point for me {{ title }} 5. Variable modifiers - Sort of an extension of 4 really but again when we're keeping things simple it is nice to be able to call on some nice simple helpers that enabe us to write less code. http://statamic.com/learn/templating/variable-modifiers --- Clearly there are things here that are good because it makes a nice change from coding in a more complex site development process (as I often do with PW), maybe of things that PW could one day use, perhaps some way of writing more code in the editor than clicks in the admin, although that must be limited by the database interactions that must be necessary. I still don't think there is a system out there that can touch PW when it comes to a tool that can accomplish almost anything in an organised, lean and powerful way.
    5 points
  3. OK, we are on. I have resumed work on this and taken a newish approach. Hope to post something by end of play tomorrow...
    4 points
  4. @dazzyweb, I just saw your discussion, sorry about that! Well, instead of adding the feature natively, we could just as well have a link in the top-left menu where documentation/support links are. Leave it up to the dev to create his own donation process if they want.. I think that'd be plenty!
    4 points
  5. One more: Loop pages in ProcessWire without building a $pageArray. This is useful for when a find() would return too many results to keep in memory. $selector = "template=pages_template"; // as an example while (1) { $p = wire('pages')->get("{$selector}, id>$id"); // get page with id bigger than previous if(!$id = $p->id) break; // assign current page's id to $id or break the loop if it doesn't exist // do stuff using $p as the current page wire('pages')->uncacheAll(); }; This served me well when I had to modify thousands of pages in one go. Works great with bootstrapping from the terminal because it doesn't affect the viewing of the website.
    3 points
  6. I'm using this function to load the addons together with the great AIOM module /** * loads css and javascript files by name of component from different css frameworks * * @param string component | name of component * @param string framework | name of framework, defaults to uikit * */ function styleAddon($component = '', $framework = 'uikit') { $min = '.min'; // you can set this empty for debugging switch ($framework) { case 'semanticui': // add css if it exists $cssFile = 'semanticui/components/'.$component.$min.'.css'; if(is_file($cssFile)) wire('config')->cssFiles->add($cssFile); // add js if it exists $jsFile = 'semanticui/components/'.$component.$min.'.js'; if(is_file($jsFile)) wire('config')->jsFiles_head->add($jsFile); break; default: // add css if it exists $cssFile = 'uikit/css/components/'.$component.$min.'.css'; if(is_file($cssFile)) wire('config')->cssFiles->add($cssFile); debug('added ' . $cssFile); // add js if it exists $jsFile = 'uikit/js/components/'.$component.$min.'.js'; if(is_file($jsFile)) wire('config')->jsFiles_head->add($jsFile); debug('added ' . $jsFile); break; } } /** * converts the style/script object to an array * * @param string component | name of component * @param string framework | name of framework, defaults to uikit * */ function toArray($obj) { $arr = array(); foreach ($obj as $key => $value) { $arr[] = $value; } return $arr; } /** * log value to javascript console * * @param string text | error message * */ function debug ($data) { // show debug only in debug mode if(!wire('config')->debug) return; echo "<script>\r\n//<![CDATA[\r\nif(!console){var console={log:function(){}}}"; $output = explode("\n", print_r($data, true)); foreach ($output as $line) { if (trim($line)) { $line = addslashes($line); echo "console.log(\"{$line}\");"; } } echo "\r\n//]]>\r\n</script>"; } of course you can remove all the debugging... i found it in the forum and for me it was helpful then in your main markup file: // stylesheets and javascripts $config->cssFiles = new FilenameArray(); // javascript files $config->jsFiles_head = new FilenameArray(); $config->cssFiles->add('uikit/less/themes/default/uikit.less'); // you can use the css version of course styleAddon('lightbox'); styleAddon('slidenav'); styleAddon('dotnav'); styleAddon('slideshow'); styleAddon('notify'); styleAddon('sticky'); // convert css/js object to array for all-in-one-minify-module $cssFiles = toArray($config->cssFiles); $jsFiles_head = toArray($config->jsFiles_head); ?> <!-- load css and javascripts --> <link rel="stylesheet" href="<?php echo AIOM::CSS( $cssFiles ); ?>"> <script src="<?php echo AIOM::JS( $jsFiles_head ); ?>"></script>
    3 points
  7. Where do i get? From here: https://github.com/IDT-media/Pages2JSON (thanks to LostKobrakai for "bug" report) What does this do? Simply adds method toJSON() to Page and PageArray elements, is capable to converting image and file arrays to URL containers, travels recursively all objects before outputs actual JSON. How to use? Simply install this module, configure data you want it to export in JSON result (similar to Ryan's ServicePages, thanks btw used some of ur code here). in templates or anywhere you need JSON output, call: $page->toJSON(); or $pages->toJSON(); Live example with template: search.php /***************************************************************** Do search *****************************************************************/ $term = $sanitizer->text($input->term); $results = array(); if($term) { $input->whitelist('term', $term); $term = $sanitizer->selectorValue($term); $limit = (int)$input->limit; $limit = $limit ? $limit : 50; $limit = $sanitizer->selectorValue($limit); $selector = "title|categories|content*=$term, limit=$limit, template=default|product"; // Prevent admin pages. if($user->isLoggedin()) $selector .= ", has_parent!=2"; // Find pages that match the selector $results = $pages->find($selector); } /***************************************************************** Output *****************************************************************/ header("Content-type: application/json"); echo $results->toJSON(); exit(); Customizing values: if(wire('config')->ajax) { wire()->addHookAfter('Pages2JSON::getValue', function($event) { $value = $event->arguments(0); if(!is_object($value)) return; $page = wire('page'); if($page->template == 'thumbs' && $value->className == 'Pageimage') $event->return = $value->size(28,28)->url; }); } Here i swap URL of all Pageimage objects in JSON response to match thumbs. Simple hu?
    2 points
  8. The thing here is to get the previous status the page had before saving.
    2 points
  9. EDIT - ignore this and see posts below I love direct sql as much as the next guy, but: $result = wire('db')->query("SELECT status FROM pages WHERE id={$page->id}"); list($status) = $result->fetch_row(); if($status & Page::statusUnpublished) { can be replaced by: if($page->status & Page::statusUnpublished) { You might also find this useful: $page->isNew();
    2 points
  10. There is this module: http://modules.processwire.com/modules/page-auto-name/ that lets you define patterns for each template (or sitewide) for automatic page renaming. Another option you might be interested in is: http://modules.processwire.com/modules/process-redirect-ids/ which allows you to access pages by their ID (no matter what else is in the URL), even though they haven't been renamed.
    2 points
  11. @JoZ3: I'm not quite sure whether I understood your request right. You want to select an image to be the cover? If so I would suggest using tags. Activate the `use tags?` checkbox in image settings and enter the tag "cover" (or something else) for the specific image. In your template you can pick this image using the following code (adapted to your needs / field names, ..): page.images.getTag('cover');
    2 points
  12. I see, this one needs a whole lot of cooking before it gets into the recipe book
    2 points
  13. <?php $last = $pagearray->pop(); echo $pagearray->implode( ', ', 'title', ['append' => ' & '] ) . $last->title;
    2 points
  14. Hi! Look for Custom Editor JS Styles Set in the field configuration and enter a path for .js file. In this file you can define your custom styles like this: CKEDITOR.stylesSet.add('mystyles', [ // Block-level styles { name: 'Heading 1', element: 'h1'}, { name: 'Heading 2', element: 'h2'}, { name: 'Heading 3', element: 'h3'}, { name: 'Introduction', element: 'p', attributes: { 'class': 'introduction'} }, // Inline styles { name: 'Link button', element: 'a', attributes: { 'class': 'button' } }, { name: 'Highlight', element: 'span', attributes: { 'class': 'highlight' } }, // Object styles { name: 'Stretch', element: 'img', attributes: { 'class': 'stretch' } }, ]); Also make sure you have Styles toolbar item enabled.
    2 points
  15. Hello there, ProcessWire has been the perfect CMS for me so far but I always missed the Laravel way of doing things when working with PW. Therefore I've built a package that will integrate Laravel into ProcessWire. It's already working out really well and I can imagine a lot of stuff to come in future. Anyways I'm hoping for some peoples support / pull requests / ideas / opinions ... Here's the link: https://github.com/hettiger/larawire Enjoy!
    1 point
  16. Inputfield And Fieldtype ImageFocusArea requires ProcessWire 2.5.6 or later This Inputfield makes it possible to select the important part of the image and use this area for different cropping options. This module is not a replacement for the existing Thumbnails module, though depending on your need it probably could replace it in many cases. I think a more flexible cropping approach than the existing Thumbnails module is useful especially when using the new html <picture> and you don't want the editor to define multiple thumbnails. Usage Create a new Inputfield ImageFocusArea and add it to the desired template. Edit a page with this template and add an image to the new field. You will see a link "Add Image Focusarea". Click the link and you will see a popup with a cropping tool similar to the Thumbnails module. Select the important part of the image, click "apply" and save the page. By default the Field hooks into Pageimage::size and automatically populates the cropping option with percentages of the center of the selected focusarea. You can always override this behaviour by calling $image->size with a different cropping option (e.g. $image->size(100,100,array('cropping'=>'center'))). The module introduces 3 new cropping options: align: This is the default if you do not override it with another cropping option. When resizing a image the module only adjusts the alignment of the crop. You will get the most zoomed-out result of these options. inside: Only parts inside of the selected area are used in the resulting image. You will get the most zoomed-in result of these options. outside: The resized image will contain the whole selected area. The surrounding imagearea will be used to reach the targetsize. This is also true for upscaling=false. Upscaling will only happen if the source image was smaller then the targetsize. API usage examples // here we force the old/usual 'center' mode: echo "<img src='{$page->image->size(200,200,array('cropping'=>'center'))}' />"; // by default if you did not define a cropping option, the cropping option gets automatically populated // Both calls will result in the same image: echo "<img src='{$page->image->size(200,200)}' />"; echo "<img src='{$page->image->size(200,200, array('cropping'=>'align'))}' />"; // the resulting image will be the center area of the selected focusarea echo "<img src='{$page->image->size(200,200, array('cropping'=>'inside'))}' />"; // to get an image with exactly the same ratio as the focusarea use width()/height() instead of a size() echo "<img src='{$page->image->width(200, array('cropping'=>'inside'))}' />"; echo "<img src='{$page->image->height(200, array('cropping'=>'inside'))}' />"; // the whole selected area will be part of the image, the surrounding imagearea will only be used to reach the targetsize echo "<img src='{$page->image->size(200,200, array('cropping'=>'outside'))}' />"; Flexible CSS Background Images Additionally you can access a new property cssBackgroundPosition, which could be useful for frontend responsive images. The visual result is similar to the cropping='align' mode, but depending on the size and postion of the focusArea and your images source and target size your mileage may vary. This property is intended to be used together with background-size: cover;. It is important that the background-image has the same ratio as the original image! <style> .cssimg{ background-size: cover; width:200px; height: 200px; } </style> <div class="cssimg" style="background-position: <?= $image->cssBackgroundPosition ?>; background-image: url(<?= $image->url ?>); "></div> Downloadhttps://github.com/phlppschrr/ImageFocusArea remember, this modules requires ProcessWire 2.5.6 or later There are still known bugs with upscaling=false, but I am not sure if it is a bug of this module or a ProcessWire bug. (fixed in ProcessWire 2.5.6) Thanks to Ryan and especially Horst for all the new great API additions for Pageimage und ImageSizer which made this module possible. This is my first module. If you notice any problems or unexpected behaviour post here or fill an issue on github. I am open to all suggestions. Do you think the cropping option names (align, inside, outside) are descriptive enough? Any better ideas? -- Edit: Renamed the Module to ImageFocusArea and updated the github link Edit 2: Reformatted this post and added some additional information.
    1 point
  17. Thanks guys, if ($page !== $homepage) { .. } Works perfect
    1 point
  18. @Martijn: I have installed this the first time now because I needed to overwrite some Admin Theme styles and also add some new. An awesome experience, - I just installed it, tipped the checkbox for including the AdminTheme-files and dropped the css files into templates/AdminCustomFiles.
    1 point
  19. @justb3a I think what @JoZ3 might mean is can this field be used to select an image from a multiple image field and use it on another page? For example (I think) he wants to use an image from a field on a product page on the home page but the image he wants is (fro example) the fifth one down in a field.
    1 point
  20. Just pushed a (major) update which adds a new feature: Change Page Template. Change Page Template: Just before the Page::loaded event the selected file is set as template file for the page. This enables you to have multiple file templates for the same page, selectable by the editor. This setting can only be applied once per a page and folders are exluded from the select inputfield. Note that a page with no associated template file will render fine with a selected file. + Changed the sorting from SORT_NATURAL flag to the natcasesort function because the flag requires PHP 5.4.0 or higher. First post is modified & please report issues.
    1 point
  21. Try this: $gallery = $page->f_multi_image; foreach($gallery as $image){ echo "<img src='{$image->getCrop('gallery')->url}' alt='{$image->description}' />"; }
    1 point
  22. Module page says it is. Also working on 2.5.20-dev.
    1 point
  23. Admin pages are best build as modules, but this will get you started in adding custom php to a backend page http://modules.processwire.com/modules/process-admin-custom-pages/.
    1 point
  24. There you find your answer.... https://processwire.com/talk/topic/1648-ok-to-change-page-name-path-after-save/#entry15232 best regards mr-fan
    1 point
  25. Lightbox is an add-on, which means that you need to include the JS and CSS files separately. It's not part of the UIKit core files.
    1 point
  26. I made a Leaflet version of this module: https://github.com/madebymats/FieldtypeLeafletMapMarker- Front-end demo: http://tegelwebb.se/leaflet-map-test/
    1 point
  27. Yes, they are equivalent, but you had: $wire->$input->post->search; instead of: $wire->input->post->search; Note the $ before input in your version. Sorry I should have explained a little more completely
    1 point
  28. First of all, you should link to the original image in the a-tag, not using the same url as the thumbnail. Next thing to check is that all UIKit-specific things like css and js are loaded correctly. Do you use the full UIKit or a customized version? If that is ok, it should work...
    1 point
  29. Just to keep PHP functions out of it $last = $pagearray->pop(); echo $pagearray->implode( ', ', 'title', array('append' => ' & ') ) . $last->title;
    1 point
  30. Great to read that you get one of the "pw" moments that shows that everything is possible... I am very glad to help and say thank you for sharing. Best regards mr-fan
    1 point
  31. I would just like to add something to Ryans great template code. I think this may be helpful for some. To add some styling to the output, you can: In "renderSitemapXML" function, change the following $out = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'; to this $csspath = wire('config')->urls->templates; $out = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . '<?xml-stylesheet type="text/xsl" href="' . $csspath . '/css/xsl-stylesheet.xsl" ?>' . "\n" . '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'; Then include this file "xsl-stylesheet.xsl" in your "css" directory. <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>XML Sitemap</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script type="text/javascript" src="http://tablesorter.com/jquery.tablesorter.min.js"></script> <script type="text/javascript"><![CDATA[ $(document).ready(function() { $("#sitemap").tablesorter( { widgets: ['zebra'] } ); }); ]]></script> <style type="text/css"> body { font-family: Helvetica, Arial, sans-serif; font-size: 18px; color: #545353; } table { border: none; border-collapse: collapse; } #sitemap tr.odd { background-color: #eee; } #sitemap tbody tr:hover { background-color: #ccc; } #sitemap tbody tr:hover td, #sitemap tbody tr:hover td a { color: #000; } #content { margin: 0 auto; width: 1000px; } .expl { margin: 10px 3px; line-height: 1.3em; } .expl a { color: #da3114; font-weight: bold; } a { color: #000; text-decoration: none; } a:visited { color: #777; } a:hover { text-decoration: underline; } td { font-size:14px; } th { text-align:left; padding-right:30px; font-size:12px; } thead th { border-bottom: 1px solid #000; cursor: pointer; } </style> </head> <body> <div id="content"> <h1>XML Sitemap</h1> <p class="expl"> Generated by <a href="http://processwire.com/">Processwire</a> this is an XML Sitemap, meant for consumption by search engines. </p> <p class="expl"> You can find more information about XML sitemaps on <a href="http://sitemaps.org">sitemaps.org</a>. </p> <p class="expl"> This sitemap contains <xsl:value-of select="count(sitemap:urlset/sitemap:url)"/> URLs. </p> <table id="sitemap" cellpadding="3"> <thead> <tr> <th width="75%">URL</th> <th width="12%">Last Change</th> </tr> </thead> <tbody> <xsl:for-each select="sitemap:urlset/sitemap:url"> <tr> <td> <xsl:variable name="itemURL"> <xsl:value-of select="sitemap:loc"/> </xsl:variable> <a href="{$itemURL}"> <xsl:value-of select="sitemap:loc"/> </a> </td> <td> <span> <xsl:value-of select="sitemap:lastmod"/> </span> </td> </tr> </xsl:for-each> </tbody> </table> </div> </body> </html> </xsl:template> </xsl:stylesheet> You can of course put the file anywhere else, just change the path in the code. Also you can adjust the styling to suit your taste/site. I hope this helps someone. P.S. though I have called the file a "stylesheet" it is actually an XSL Transformation You can read more here http://www.w3schools.com/xsl/xsl_intro.asp
    1 point
  32. Pass the product to renderAddToCart: echo $modules->get("ShoppingCart")->renderAddToCart($product); The method tries to use the current page as the product page for which to render the button if none is passed as its argument, but since you're calling it from a non-product page without an sc_price field, it doesn't find anything to render.
    1 point
  33. I used Drupal 6 and 7 and also liked it. For awhile I was searching for a simple clean anbd easy CMS, tested modx and found a note about PW... Changed to PW and I love it! No bloated html output and a awesome api. Build websites and write modules is so easy with PW!
    1 point
  34. 1 point
  35. I've only just switched to PHPStorm from DreamWeaver - I don't think I could handle more than one change a decade
    1 point
  36. The problem happened to be related to old session files that I transferred when moving to the new server. Once I deleted all session files in assets/sessions on the new server, PW picks up the $config->httpHosts array and the error message in the backend disappears.
    1 point
  37. I don't know if Ryan can be bullied into supporting field dependencies with repeaters but maybe he'll look at it if enough people chime in to request it. I have a repeater that's full of dependency potential. Empty text field that, if it contains data, needs a modifier field to appear. Categories that depending on which category is selected would require additional fields relevant to that category. etc. It would be very useful to streamline the interface and reduce potential user input error If I could only display the fields relevant to the data (all of which is contained within the same repeater. If the fields won't save, there's no point because chaos will ensue but if this could be made to work it would add a whole new level to repeater love from me. So...pretty please?
    1 point
  38. @Lars282 Soma and Slkwrm have it right. Keep in mind that saveReady is called after it's been confirmed the save() will definitely occur, and right before the save actually occurs. So this is the ideal hook for you to use in your case. This is correct. We don't yet have a property $page->statusPrevious property like we do for parent or template. So there's no way for you to know what the previous status was short of loading another copy of the page, or just querying the database like in the example. But now you've got me thinking I may need to add a statusPrevious property in a future version. For your hook attachment code, I would suggest this: public function ready() { $this->pages->addHook('saveReady', $this, 'sendMailOnPublish'); } …basically the same as what Soma suggested, except that I would add it to $this->pages directly since there is only ever 1 instance of $pages, making it slightly more efficient to do this way. Your actual hook function will be in the same class as your ready() function, and would resemble the one Soma posted. This is correct. If there was no $page->id, it would be a new/unsaved page, and you wouldn't want to go querying the DB for it as we know it wouldn't be there. So that's what the $page->id check is for.
    1 point
  39. I don't have a simple solution to this one, but will do more thinking about how I could have ProcessWire provide a hook like Pages::statusChanged or something like that. But until we have something like that, here are a couple ways you could do it: Option 1 Add a hook to Pages::saveReady and have your hook function do something like this: Pages::saveReady hook $page = $event->arguments[0]; if($page->id && $page->isChanged('status') && !$page->is(Page::statusUnpublished)) { $result = $this->db->query("SELECT status FROM pages WHERE id={$page->id}"); list($status) = $result->fetch_row(); if($status & Page::statusUnpublished) { // page is about to be published // send your email } } Option 2 The other option would be to change your workflow such that user submitted pages went into a different parent than the live ones. For instance, user-submissions might go into parent /pending/ and published submissions would live in /live/. Then you could have your hook monitor for when a page is moving from /pending/ to /live/. If you wanted to, you could also have it take care of the publishing automatically: Pages::saveReady hook $page = $event->arguments[0]; if(!$page->parentPrevious) return; // if page is not being moved then stop now if($page->parent->name == 'live' && $page->parentPrevious->name == 'pending') { $page->removeStatus(Page::statusUnpublished); // send your email }
    1 point
×
×
  • Create New...