Leaderboard
Popular Content
Showing content with the highest reputation on 10/22/2014 in all areas
-
Just a reminder to all the module devs out there. If you commit an update to your module to GitHub, you don't have to wait the normal day or so for it to be updated in the modules directory, Modules Manager, Check for Updates link, and the in new Upgrades Module. You can simply edit the module in the modules directory and save it again. That should update the version from Github. If you are using the info.json approach then just manually edit the version number. Often this is not that important but if you discover a critical bug and want to make sure people can get the new version easily and immediately, this is a good idea!6 points
-
Simple logic issue of your code. 1. User logged in? ... redirect 2. Form submitted, check and login 2. User not logged in show login After sending the form, he's not yet logged in... you log them in later (but still show the form as if not logged in), but don't redirect after the login. So you get what you have.4 points
-
In this tutorial we make a simple function that becomes part of every PageArray. Once hooked to the PageArray class, you can call this function from anything returned from $pages->find(), $page->children(), or your own page references like $page->categories from the blog profile, etc. It essentially becomes a new function available to you from any PageArray anywhere in your site. First, lets look at what convenience the hook function adds and how we might use it. We'll call the hook function "renderLinks", but you could of course call it whatever you wanted. We call that renderLinks() function from any PageArray, and it returns a string representing that PageArray as a list of links. By default, this renderLinks() functions separates each page with a comma, and outputs the page's title as the anchor text. We can change that to be anything by specifying arguments to the call. The first argument is the delimiter, which defaults to a comma ", " if not specified. The second argument is the name of the field to output, which defaults to "title" if not specified. Next are 3 examples of how this renderLinks hook function could be used. Usage Examples: Example 1: render a comma-separated list of links: echo $pages->find("parent=/")->renderLinks(); Output: <a href='/about/'>About Us</a>, <a href='/contact/'>Contact Us</a>, <a href='/site-map/'>Site Map</a> Example 2: render a <ul> of $categories links: <ul> <li> <?php echo $page->categories->renderLinks('</li><li>', 'title'); ?> </li> </ul> Output: <ul> <li><a href='/categories/category1/'>Category 1</a></li> <li><a href='/categories/category2/'>Category 2</a></li> <li><a href='/categories/category3/'>Category 3</a></li> </ul> Example 3: render a breadcrumb trail: <p class='breadcrumbs'> <?= $page->parents->renderLinks(' / ') ?> </p> Output: <p class='breadcrumbs'> <a href='/parent1/'>Parent 1</a> / <a href='/parent1/parent2/'>Parent 2</a> / <a href='/parent1/parent2/parent3/'>Parent 3</a> </p> Those examples above show some of the potential of how you might use such a function. Next is the hook function itself. In order to be available to all templates in your site, it needs to be defined somewhere consistent that is always loaded... Where to put the hook function: If using the basic profile (that comes with ProcessWire) you could put the hook function at the top of your /site/templates/head.inc file. If using the Foundation or Skyscrapers profile, you could put the hook function in your /site/templates/_init.php file. This is the method that I use. If using something else, you could create a /site/templates/_init.php file with your hook function(s) in it, and then edit your /site/config.php to point to it with the $config->prependTemplateFile = '_init.php'; so that it is automatically loaded on every request. Note that the name "_init.php" is not required, you can name it whatever you want. You could put it in an autoload module... but that might be overkill here. The actual hook function: wire()->addHook("PageArray::renderLinks", function(HookEvent $event) { // first argument is the delimiter - what separates each link (default=comma) $delimiter = $event->arguments(0); if(empty($delimiter)) $delimiter = ", "; // second argument is the property to render from each $page (default=title) $property = $event->arguments(1); if(empty($property)) $property = "title"; // $out contains the output this function returns $out = ''; // loop through each item in the PageArray and render the links foreach($event->object as $page) { $value = $page->get($property); if(!strlen($value)) continue; // skip empty values if(strlen($out)) $out .= $delimiter; if($page->viewable()) { // if page is viewable, make it a link $out .= "<a href='$page->url'>$value</a>"; } else { // if page is not viewable, just display the value $out .= $value; } } // populate the return value $event->return = $out; }); If using PHP before 5.3, or using an older version of ProcessWire, you'll need to change the first line to this (below). This syntax also works with newer versions as well, but it's not as pretty as the new syntax. wire()->addHook("PageArray::renderLinks", null, 'hookRenderLinks'); function hookRenderLinks(HookEvent $event) {3 points
-
Why all this complicated like moving and hooking and redirecting. I think it's as simple as only display news to a certain date time expired, and have a link to older news will just show all from a certain date time backward. This could be done with a urlSegment or a physical page "older-news" that only lists, well older news. No need to go fancy complicated. News pages stay where they are, chronologically.3 points
-
@JanRomero: +1! if the images are the only difference, this is much better. I have a script that does something along this, maybe it is a good starting point: pwimg_(as-starting-point).zip EDIT: found that old thread, where I initially created that script. It has some htaccess rules that also can be a starting point if one want to go the htaccess route: https://processwire.com/talk/topic/4668-protect-original-images-in-siteassetsfiles/#entry461893 points
-
Sorry for poor communications from my part. New shop module is currently in closed beta testing. I am pretty busy at the moment (both work and personal), so there is not too much focus on this. For the pricing I am thinking something like 50€ - 99€ for single site license. Also currently (slowly) building full featured shop profile, that would be single purchase and free to use parts or fully as many times as wanted (single site license required for all new shops though).3 points
-
This is a very basic guide on how to optimize a ProcessWire page for speed. It doesn’t go into the depths of optimization and perfect render paths but will provide you with some proven ProcessWire methods for faster websites. The big problems that are easy to fix are what we aim for. You want quick improvements? Then read on… First let's have a look ath the following graph. Those are the areas, we want to improve. Source: http://httparchive.org/interesting.php?a=All&l=Oct%201%202014 Clean up your HTML Look at your HTML source code. Are there any unnecessary parts? Remove anything that might not be needed and try to keep your markup as clean as possible. Avoid using too many external JS libraries or other tools. It is okay to include jQuery from a CDN, because most visitors will already have cached the file. Too many of those external requests will slow down the page. If possible, try to avoid render-blocking Javascripts and move your script tags to the end of the page, right before the body. In most cases, your Javascript will enhance your content but doesn’t need to fire before the site is rendered. Always think if you need to include another library or the fourth webfont on your site. Minify Markup The next step to save some bytes is to remove all whitespaces from your markup. It doesn’t have to look nice, it has to be loaded fast. We perform this trick with our new super-weapon: The AllInOneMinify module for ProcessWire. Install it like every other module for ProcessWire. Once activated, go to the module settings and tick the checkbox for “Minify HTML” and look at your sites source code. It should be minified. AIOM can handle conditional browser comments. If your layout depends on whitespaces you could “force” them by putting an into the markup. Optimize the CSS Now we’re heading for the next larger part of a usual website. We will combine all CSS files and then remove anything not needed (whitespace,comments) from it. Before we start, make sure your CSS files only contain rules that you really use. Especially if you’re using a framework like Bootstrap, most of the selectors are never used. Remove them carefully. We need the AllIneOneMinify module from the previous step again. After installation, open the template file where your HTML header is generated. We will now replace all stylesheet tags with a single file. AIOM needs to know all CSS (or even LESS) files, relative to your template folder. It will then output a link to a single, compressed CSS file. You might have this in your HTML head: <link href="<? echo $config->urls->templates;?>/css/grid.css "rel="stylesheet" /> <link href="<? echo $config->urls->templates;?>/css/style.css“ rel="stylesheet" /> Replace all links to Stylesheets with the single tag like this: <link href=”<? echo AIOM::CSS(array(‘css/grid.css’,’css/style.css’)));?>” rel=”stylesheet”/> You pass an array with the file names to the AIOM method CSS. It will return a link to the file. AIOM takes care of image urls inside CSS. It will detect changes in the source file and only generate a new file if necessary. While developing, you might want to turn on the “Development” checkbox in the module settings. Make JavaScript tiny Do the same as you do to the CSS to your Javascript files. First, clean up the code. Then install AIOM and compress all JS files into a single file using the AIOM::JS method that works as the AIOM::CSS method. For best results, think about including scripts like jQuery from a CDN and put your scripts below the content, before you close the body tag. Also note that the order on how your throw your JS files into AIOM might be important, depending on the code inside. Get the right image size. ProcessWire comes with great image tools. Use them, to make images exactly the size you need them. You don’t have to serve that little thumbnail with over 3000px length just because the editor wasn’t able to reduce the size. Example: Your designer wants to have a slider image with a maximum size of 600x320 pixel. To output the image with that exact dimensions, use the API accordingly: $sliderImage->size(600,320)->url; An even better way would be to use adaptive images or the new srcset attribute combined with a JS fallback. Then your site only delivers the image size as needed. Hint: Play around with the image quality setting in the config.php. Maybe you don’t need images with a JPG quality of 90+. Compress the images further with minimize.pw To make images even smaller, we can use the minimize.pw service. This service will compress images nearly lossless by using more complicated tools to reduce the size of PNGs and JPEGs. By doing this, you remove bytes from the largest chunk of your website weight. minimize.pw is free for 2000 images. Just enter your E-Mailadress and receive a free key Then you have to install the ProcessImageMinimize module and enter they key. You can now activate the option to automatically compress every image uploaded. It is fail-safe and will compress images in the background. Please note, the automatic mode only works with images uploaded AFTER you have activated the module. You can manually select image fields with the ->mz() API method. Just include it before you output the image in your template file: $myImage->width(300,300)->mz()->url; We've closed the service. You could use something similar like Imgix ( https://www.imgix.com/ ). Activate GZip compression on your site Another method to speed up your site is to activate GZip compression. The server will then send all files compressed to the client. This works with nearly all browsers and the CPU power required is minimal. You can tell your server to do this, by adding those lines to your .htaccess file in your root directory. Please take care, that you do not overwrite the ProcessWire rules in the file! For best results add them on the top of the .htaccess file: <IfModule mod_deflate.c> AddOutputFilter DEFLATE js css AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html </IfModule> This was taken from another forum post. Tell the client to cache stuff To make repeating visits faster, we can tell the browser to cache special files for a longer period of time. Again, add this on top of your .htaccess file: <IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 seconds" ExpiresByType image/x-icon "access plus 1 year" ExpiresByType image/jpeg "access plus 1 year" ExpiresByType image/png "access plus 1 year" ExpiresByType image/gif "access plus 1 year" ExpiresByType text/css "access plus 1 month" ExpiresByType text/javascript "access plus 1 month" ExpiresByType application/octet-stream "access plus 1 month" ExpiresByType application/x-javascript "access plus 1 month" </IfModule> <IfModule mod_headers.c> <FilesMatch "\\.(ico|jpe?g|png|gif|swf|woff)$"> Header set Cache-Control "max-age=31536000, public" </FilesMatch> <FilesMatch "\\.(css)$"> Header set Cache-Control "max-age=2692000, public" </FilesMatch> <FilesMatch "\\.(js)$"> Header set Cache-Control "max-age=2692000, private" </FilesMatch> <FilesMatch "\.(js|css|xml|gz)$"> Header append Vary: Accept-Encoding </FilesMatch> Header unset ETag Header append Cache-Control "public" </IfModule> Remember, that this caching might be annoying while developing the site. Use the internal cache (or ProCache) Another trick to make the site faster is to use a caching system. This will “store” your rendered site so you don’t have to query the database that often. We can either do this with the internal cache of ProcessWire or use the commercial, official ProCache module. Using the build-in system, you go the the setting page of a template and open the “Cache” register. You can now set the Cache time and what happens if something changes. The settings depend on the content of the site. Mostly static content can be cached longer and you might not need to reset the cache every time. Dynamic sites will need shorter cache times. ProCache (buy here) is even faster because it will bypass PHP and the database. Files are served directly as HTML. Please note, that caching might make the site faster but it can create new problems. Use with care. Summary Keep your code as clean as possible. Remove anything unnecessary and then compress HTML,CSS and JS using the AIOM module. The largest part of your page weight are images. Keep them small by using the appropriate dimensions and consider services like minimize.pw. In the end, use intelligent caching and buy ProCache. Following this guide takes not more than an hour but can speed up your site and make your visitors happy. This was just a quick overview of techniques to optimize your page speed. There is plenty of stuff you can do but the steps above are a good first step. Maybe you can share your favorite methods (or links) to start the discussion.2 points
-
MarkupAdaptive This module aims to be a helper for developing an adaptive site. MarkupAdaptive is a module that injects classnames representing 'media queries'. Fire events after the browser is resized and fires an event when a media query is changed. Optionally it can write a cookie with the ‘media query’ classname of the current viewport size. The main purpose of this module is about syncing media queries with javascript. Say I want to have a slider on the iPad but don't want that slider on the phone I could now destroy the slider exactly on the right time. You could respond server side with this cookie, but keep in mind that you then need a workaround for the default caching solutions. (template cache or ProCache) The module script works with injected media queries and a HTML element tested against those. This javascript process starts real early in the load process and is extremely fast. It starts even before the body tag is parsed. In Explorer 7 and 8 clientWidth is used to pinpoint the “classname of the viewport size”. To support Explorer 7 and 8 your media queries should be specified in pixels. In the wild An working example of the module is hosted on hosted on lightning.pw Instant ProcessWire Hosting from conclurer.com. Please don't forget to view the console.log(). The site doesn't use any media query in the stylesheet. Not that I recommend building adaptive sites without media queries. . How to install Install the module At least open the Module configuration, optionally save it. Insert the below code in the HEAD of your html file <script><?php echo $modules->get('MarkupAdaptive'); ?></script> Javascript methods available when using MarkupAdaptive. ( More instructions like Event support IE7 & 8 are available in the 'example template' packed in the module folder ) /** * Getting information with Javascript. * */ // How to catch the end of a resize (with jQuery) $('html').on('resized', function(e) { console.log('Browser window is resized'); }); // Respond on a media query change $('html').on('mediaquerychange', function(e) { // Get the old class name before the “mediaquery” change has occurred var oldClass = MarkupAdaptive.getOldClass(); // Get the new class belonging to the current “mediaquery” var newClass = MarkupAdaptive.getClass(); console.log('mediaquerychange, from: “' + oldClass + '” to: “' + newClass + '”'); }); // Get the current class var current = MarkupAdaptive.getClass() // Get the old class, the class before the current var old_class = MarkupAdaptive.getOldClass() // Mediaquery JSON object which originates from your Modules config var sizes_object = MarkupAdaptive.getJson() // Mediaquery JSON object which originates from your Modules config' var array_with_classnames =MarkupAdaptive.getArray(); // Is the current browser IE8 (returns true/false) MarkupAdaptive.isIE() // (bool) // Is the current browser IE8 MarkupAdaptive.isIE(8) // (bool) // Is the current browser less then or equal to IE9 (lt, lte, gt, gte) MarkupAdaptive.isIE(9, 'lte') // (bool) // get the cookie, when checked in the module configuration function getCookie(name) { var match = document.cookie.match(RegExp('(?:^|;\\s*)' + name + '=([^;]*)')); return match ? match[1] : null; } console.log('Classname cookie value: ' + getCookie('MarkupAdaptive')); Special thanks to all the people from conclurer who made it possible to host MarkupAdaptive. When you're searching a lightning fast hoster. You should consider lightning.pw. View on GitHub Download GitHub2 points
-
Me too. What I thought this thread would be about updateing the module pages for 2.5 compatibility info (which is more important). I did mine some time ago.2 points
-
If you access the field you get a WireArray of image objects, and each has a method url (I think), it's not a property or a field. $imgs = $pg_settings->get("banners_slideshow"); $imgs->first()->url; // the first $imgs[0]->url; $img->eq(0)->url; // etc foreach($imgs as $img) echo $img->url; Forget about print_r() on arrays and object, you won't get useful infos most of the time it's overkill. Maybe have a deep read here http://processwire.com/api/fieldtypes/images/2 points
-
I think he means that when he does $pages->find($selector)->suhosinRandomTimed(3, "c"), $num will still be "2" and $seed will be "Ymd". Like I explained earlier, this happens because in the given example suhosinRandomTimed() -function, the arguments are not read from the $event-object. Here's an example of a hooked method that would work with arguments as expected function suhosinRandomTimed($event) { $pages = $event->object; $num = $event->arguments("num"); $seed = $event->arguments("seed"); if(!$num) $num = 2; if(!$seed) $seed = "Ymd"; // ... rest of the code here }2 points
-
@muzzer: You need to retrieve all arguments from the HookEvent-object. ProcessWire will never add any other arguments to the hooked method call. In your case, you can get the passed seed-argument with $event->arguments("seed") or like you noticed, with $event->arguments(0). To implement optional arguments, you can do something like $seed = ($event->arguments("seed") !== NULL) ? $event->arguments("seed") : "Ymd"; If you have any other arguments than $event in the definition of your hooked function, I would remove them for clarity and use the method defined above. Or if you think it's nice to see the default values in the function definition, you need to check if the arguments are set in $event and then overwrite them.2 points
-
You could redirect the images to a php file that decides which version to serve. That way you can serve the same cached version of the page to everyone, but when the browser requests the image file, the login check is performed. However, are the images really the only difference between signed-in users and guests?2 points
-
I don't understand much from DB things, but hopefully we never run into something like this with PW: drupal-pre-auth-sql-injection-vulnerability: https://www.sektioneins.de/en/advisories/advisory-012014-drupal-pre-auth-sql-injection-vulnerability.html https://www.drupal.org/SA-CORE-2014-005 https://www.drupal.org/node/23572412 points
-
Sure, you can do whatever you want with PW! Put something like this in your template file, or change it to extend the WireArray class if you'd like // Adding the method "suhosinRandomTimed to the WireArray class $wire->addHook('WireArray::suhosinRandomTimed',null,'suhosinRandomTimed'); // Define the method, I added $num and $seed to make this easy to demonstrate function suhosinRandomTimed($event, $num = 2, $seed = 'Ymd') { $pages = $event->object; // This is the WireArray object, more than likely will be pages if(is_string($seed)) $seed = crc32(date($seed)); srand($seed); $keys = $pages->getKeys(); // changed all instances of $this to $pages since I'm not defining within class $items = $pages->makeNew(); while(count($keys) > 0 && count($items) < $num) { $index = rand(0, count($keys)-1); $key = $keys[$index]; $items->add($pages->get($key)); array_splice($keys, $index, 1); } $event->return = $items; // return the pages } $p = $pages->find("template=someTemplate")->suhosinRandomTimed(); // Call the method on the results of $pages->find echo $p->render(); Just change the function's body to do whatever you need it to be and you should be good.2 points
-
To add some background: the thought behind this is called Responsive Web Design + Server Side Components (http://www.ress.io) The big advantage over "just responsive" is that you don't only have a responsive site, but instead cater to the various environments. For example, you could assume that users with mobile devices almost always operate on a smaller bandwidth with a bigger latency. You might want to deliver only the JavaScript that's needed for the mobile version, not necessarily all the bytes for the full fledged desktop version. Or, to turn it around, auto-load videos on the not-mobile versions, and just have images on the mobile version… you name it. Horst in #12 also has a good use case. This is especially necessary, when you have the – nowadays somewhat old-fashioned – opinion, that web sites should also work without JavaScript. At least the basic functionality. It is a bigger effort though and has some pitfalls, one of which is caching. We don't have issues with that, but you could easily run into trouble. As mentioned before, TemplateCache can only cache whole sites. You could use MarkupCache instead, which is more work again, but should give you the control you need. With ProCache i haven't been working yet, but I assume from what I've read that it's a TemplateCache on steroids. We are currently working on a caching solution somewhat similar to ProCache, which also respects the user's environment and the version they get delivered – for which this module comes in handy again This is yet one of the harder issues.2 points
-
Websites often provide content not only as on list of stuff, but with some sort of category. The most flexible way in ProcessWire to manage such a categorization are with PageFields. Form example with a structure like this. - Magazine (magazine) - Articles - Article 1 (article) - Article 2 - Article 3 - … - Categories - Category 1 (category) - Category 2 - … Templatenames in parentheses Now all articles have a url structure like: "…/magazine/articles/articlename/" The categories are looking like: "…/magazine/categories/categoryname/" But it can be useful to also provide the articles as part of the categories like this: "…/magazine/categories/categoryname/articlename/" Because ProcessWire doesn't provide such functionality by default, we'll use urlSegments. These have to be enabled in the template-settings for the category template. This template therefore fulfills two different jobs. Displaying a list of containing articles, as well as rendering the articles which are linked by the list. A simple example of a existing category.php could be: <?php // category.php $articles = $pages->find("template=article, category=$page"); // This example uses a deligated template approach. // Feel free to use your own way of templating, // but this is also a simple way to explain this. $content = renderArticleList($articles); include("./_main.php"); Now we need to include the logic to seperate the default rendered article-list to the now added rendering of the called article. <?php // category.php // Throw a 404 Error if more than one segment is provided if($input->urlSegment2) throw new Wire404Exception(); if($input->urlSegment1){ // Show the called article // Sanitize the input for pageNames $name = $sanitizer->pageName($input->urlSegment1); // Search for the article with this name $article = $pages->get("template=article, name=$name"); // Throw an 404 error if no article is found if(!$article->id) throw new Wire404Exception(); // Explicitly set the original url of the article for the <link type="canonical" href=""> tag $article->canonical = $article->url; // Render the page, like if it was normally called. // $page->url will not updated to the "categorized" url for the rendering-part // so you need to have that in mind if you provide some sort of breadcrumb echo $article->render(); }else{ // Show the list of articles of the current category $articles = $pages->find("template=article, category=$page"); // The generateCategoryUrls() function is new, because // $page->url would provide the wrong urls. // Details are provided later $content = renderArticleList( generateCategoryUrls($articles, $page) ); include("./_main.php"); } Now if we call this "…/magazine/categories/categoryname/articlename/" we'll get the right article rendered out instead of the article-list. Now we need to talk about the article-list, which would - without changes - still render the "wrong" urls to all those articles. Therefore I added the generateCategoryUrls() function. This function iterates over the pageArray and adds a second url to all those articles. <?php // part of _func.php function generateCategoryUrls($list, $category){ foreach($list as $item){ $item->categoryUrl = $category->url.$item->name."/"; } return $list; } The last thing missing is the actual template which gets rendered by renderArticleList(). This would normally call for $article->url to get the url to the article. We want this to render our second url if we are on a category site. To let the template still be useable by non category sites, we just change the parts, where to url is used form the current $article->url to $article->get("categoryUrl|url"). Only if the additional urls are provided they get rendered or it falls back to the normal urls of the articles. There we go, with such a setup all categorized articles are reachable via both urls. A small addition to explain the $article->canonical I used in the category.php. For SEO it's not good to provide the same content on multiple pages without explicitly declaring which of the duplicated ones should be the original / indexed one. By providing the following link tag we provide this declaration. The extra field I use isn't really necessary, because $page->url still is the standart ProcessWire url of the shown article. But I like this to be visibile in the code, that this is a dublicate. <link rel="canonical" href="<?php echo $page->get("canonical|url") ?>"/> Hope you like the explanation. Feel free to give feedback on this. Based on the example shown in the wiki: http://wiki.processwire.com/index.php/URL_Segments_in_category_tree_example1 point
-
Hi Guys, at this night I've pushed some changes to my master branch of ProcessAbbreviate. The following features are included in version 0.2.1 Support for the language attribute of <abbr/> Configurable auto mark up feature Bug fixes Support for the language attribute of <abbr/> I've altered the database table to save the language attribute for some kind of multi language support. This attribute is usable for screen readers to change pronunciation for the given abbreviation. Additional its usable in multi language systems for better/saver language handling. Configurable auto mark up feature Well, I would call it experimental. (It have to activate manually) I've just done some basic tests in auto marking up abbreviations. I would be happy to get some feedback if it could be more precise or so. If you have two or more abbreviations with the same abbreviation (text), the first abbreviation saved in the database will be auto marked up. So this feature will ever be a little support for marking up abbreviations, but you have to check these abbreviations on your own to be secure that the right abbreviation is marked up. Bug fixes There was a bug by uninstalling the module Abbreviate which did not delete the admin page created by installing this module. (thanks teppo) So I hope you enjoy this additions and give ProcessAbbreviate a try. Any feedback are welcome! regards, Sven1 point
-
It seems like OR in dependencies is not working for radio buttons. I want to show a field only some specific options of the radio input "ad_frequency" are checked. I tried this in field dependencies settings: ad_frequency=1082, ad_frequency=1083, ad_frequency=1084 If I set it to a single radio option like ad_frequency=1082 everything is working as expected. In the docs it says that this will be implemented. Does anyone know, when?1 point
-
@jordanlev: Commenting quickly on this. You want to use PageTables - you'll love them. They will provide your project the ability to include the product locations and variations on the same page with your product. PageTable-fields have their own template attached to them. In your case, you can probably go ahead and use the existing product-variation and product-location templates. You just create two new PageTable-fields, one for each template and then attach the new fields to your product-template. For more information, check this post for an example https://processwire.com/talk/topic/6417-processwire-profields-table/?p=63119. And don't be mislead by the term "field", these are pretty badass fields.1 point
-
I don't think you need to place your data into admin branch. Why? It's meant for admin stuff and it would be no problem to put them in the root of home. If you don't have a template file they are not viewable or you could protect them by removing guest view access. I can't agree with that the page tree and editing sorting deleting or crud if you will is confusing. Quite the opposite. And this is from a experience in about dozen different projects with no technical savvy users. Often we don't even need to explain them. While you of course can easily build custom crud and stuff I thonk you do too much for thinga already there. You don't have to build that really. Edit. Don't get me wrong I don't mean it's all completely wrong. Just scratching my head and you must be hating me already To me it sounds like. Ok I want only data, no frontend so I pllace them in admin/ .. but then users can't access them or edit them so I create my rails mvc crud to let them do edit them. While you can easily place them outside admin/ and let PW handle all this jus fine. But maybe I don't get what really is the reason. Also you can render part of the tree in your module and have them edit using pw edit screen and sort or delete them with a fee lines of code.1 point
-
happy to report that by upgrading to latest Page Rename Options that this bug has been fixed for me. It was a bit scary when actual usernames were being modified when you added/edited your display name and I couldn't gain access but this update to version 0.1.4 seems to fix it. This would have been a serious issues for my clients to say the least. Thanks for that insight Adrian, appreciate it!!1 point
-
The problem with a module like this is that it is unlike WP with its many themes which have different layouts .. For #1: I think you can easily pull that off with CSS. What I will need to add however, is the option to also output a featured image for a full single post [blog-post.php] (currently I have implemented this for $small posts only). Same as the current implementation, one will have the choice for that to be output either above the post-headline or below the post-body. In your case you'd probably go for 'above' post-headline and using CSS you can place your headline on top of the featured image. I'll try show you example CSS on how to do it... For #2: I will need to think about how those can be implemented (forum any/all ideas welcome, thanks!). I think it is an important feature. This will probably have to be implemented on the GUI side. It will have to be configurable, i.e. what social media sites to show, their icons, etc...This feature may have to wait for a while though...I want to get it right... Thanks for the ideas.1 point
-
Enable the core module "Page Path History" and it will take care of the redirects for you.1 point
-
There's a nice tuto by Ryan https://processwire.com/talk/topic/4834-simple-hooks-tutorial-turn-a-pagearray-into-a-list-of-links/1 point
-
Like it a lot, especially the configuration options in the GUI. But to be honest, I think I’d use a pretty robust solution like enquire.js if I’d want media query handling via JavaScript.1 point
-
I use this code. try { $login = $session->login($user, $pass); if($login && $login->id) return true; else return false; } catch(Exception $e) { return $e->getMessage(); }1 point
-
I always use google to find my answers, although without the site:processwire.com/talk (PW forums tend to be the top 10 results anyway). But for some reason I couldn't find it anywhere. Guess my searched weren't formatted as they should've (overcomplicated things) Thanks once more1 point
-
1 point
-
I'm with mr-fan -- I have an analogous data structure. Reading the code in InputfieldPage.module isValidPage(), I come to the conclusion that the field's option to select pages using "Custom PHP code to find selectable pages" should not be used until you can actually save the pages, which you can't right now because they don't validate. I just replaced if($field->findPagesCode) { // TODO: we don't currently validate these } with if($field->findPagesCode) { // DONE $inputField = $field->getInputfield( $editPage, $field); $validPages = $inputField->findPagesCode( $editPage ); // if the page is in the list, it's valid. No more questions asked! return $validPages->get( 'id=' . $page->id) ? true : false; } Can't it be this simple? I must be missing something? Is it a performance issue? I'll submit a patch and see whether it passes mustard with the head dogs1 point
-
Chris, This is a total stab in the dark here, but any chance you also had either the AutoName or PageRenameOptions module installed? There was a bug in both that allowed for system template names to be changed - would only happen to the user template if the title field was added (it's not there by default, but it is added with this module). The bug has been fixed on both modules as of today, so if that was the issue, make sure you update those modules and everything should be fine. The good thing to know is that it would have just been a matter of opening up PHPMyAdmin to see the name of the user in the database - log in with that and you'd have been fine. So very sorry if it was one of those modules that caused the problem, but glad you managed to restore things ok. If not, I'll defer to kongondo.1 point
-
Thanks to both for your help and answers... wish I could mark both as the solved post Cheers guys!1 point
-
Definitely recommend it. I normally wait until V1.2 of any software I rely on but having installed the beta the day it was available I was surprised just how stable it was. I'm a So finding boot up,shutdown and general speeds to be snappier on a 2011 macbook. I'd say go for it. You can always install on a partition and test if you're unsure.1 point
-
Update was a breeze. Really like the overall look of Yosemite. On the development front, PHP 5.5.14, Apache 2..4.9. There's some useful Apache module wich are not enable by default (mod_rewrite for example) but nothing too difficult to fix. For complete instructions to install a LAMP stack on Yosemite this guide is very handy. Safari 8.0 is crazy fast and may become my primary browser instead of Firefox.1 point
-
I'm using XAMPP and had to update/fix it. (Fix was to insert one line in one specific configuration file. So it was more like copy and paste fix).1 point
-
Already running Yosemite on a 2014 MBA. I was really eager to get my hands on a feature that most people probably find rather whatever, but I loved it from the moment Apple first showed it at the keynote introducing Yosemite – doing iPhone calls on a Mac. (It does actually work well for me. No more having to pick up the call on the iPhone, plugging in headphone to have my hands free etc. Just accept the call on the Mac and talk.) Other than that, I'm okay with the new look. No idea why a lot of people are desperately looking for ways to replace the Finder icon, the folder icons in Finder and get Lucida Grande back. Also, I love the new iOS-style notification center. Oh, also, second-best feature in Yosemite: the F11/12 keys for controlling the sound volume now don't make sound any more by default. I'm really not going to miss those sounds at the start of each Skype call when everybody's adjusting their volume … Since I don't use MAMPP or the local Apache, no issues with that. However, I had to “repair” some Ruby gems that I had installed for whatever reasons. I really only use Sass/Compass and scss-lint, so I have no idea why those gems are even installed. Other than that, everything seems to work fine, I didn't even notice that the upgrade took longer than expected because of all the Homebrew stuff I have installed.1 point
-
Another solution could be to wrap a function around the include for the remote file. This way it gets opened in its own scope and doesn't override your $config object: function readRemoteConfig($pathToFile) { $config = new stdClass(); // it is enough to use a StandardObject here, - without that, PHP will raise a 'notice' I believe. include($pathToFile); return $config; } $remoteConf1 = readRemoteConfig("path/to/remote1/site/config.php"); $remoteConf2 = readRemoteConfig("path/to/remote2/site/config.php"); $remoteConf3 = readRemoteConfig("path/to/remote3/site/config.php"); // and your (local) $config isn't affected or touched in any way1 point
-
Damn, there's too much to like in this thread....1 point
-
Take a look at Soma's gist. It loops through all the fields of your page and displays a form. Then on Submit of the form it again loops through each field and saves the value. It also includes all styles and scripts that you need for your form to work on the frontend. This is working great for my frontend form. If you need help implementing it, let us know.1 point
-
@muzzer Check out Teppo's ProcessWire hooking article on this sort of thing and also look at the last two hooks added in the HelloWord example module. You'll see that Ryan's added the ability not only to externally inject new methods to Wire-derived classes but to inject new properties too.1 point
-
@Muzzer - Nope, that line was a stray, lol. I was eating Capt'n Crunch, thinking, and typing all at once. Glad the rest of it was of use though!1 point
-
Just a pointer for those interested in why the first() method that diogo mentioned solved this; if you look at your page field "food_types" and switch to the details tab, you probably have the first option selected, like this... ...which is setup to return an array of pages, even if that array only has a single page in it. Now that's why you need to call first() as you need to select a page from the array that $page->food_types was returning. /** * Examples for a page field setup to return an array of pages... */ echo $page->food_types; // This won't work for an array return as you haven't drilled down to a page entry yet. $p = $page->food_types->first(); // Ah, now $p holds a page. echo $p->title; // And now we can show the title. echo $page->food_types->first()->title; // This works too, no need to assign to a variable if we don't want to. You stated in your opening post that food_types only has one page selected... Now look at the other two options for your page field in the screen shot. Both of those options return a single value when the page field is referenced. If you had picked either of those two options then your code would have worked as you'd have been given a page (or 'false' or a NullPage) directly without having to fish it out of an array. Anyway, hope that helps explain things a little more.1 point
-
Andi, nico has build an SEO tool not an encyclopedia.1 point
-
http://www.foodloversdiary.com/good-stuff/the-bowl-of-good-food-we-can-all-invest-in/ and... https://twitter.com/foodloversdiary/status/524323670630469634 In case anyone wants to retweet...1 point
-
1 point
-
TinyMCE as the default RTE ? I'm guessing the new growth is a combination of things...2.5, RenoTheme, ListerPro, ProFields, lull from other CMS progress, friendly community. And in the background, Ryan's constant patience, enthusiasm, productivity and all round genuine positivity and transparency. At least they're my own magnets. Interested to read others interpretation.1 point
-
Post title kind of says it all. Well, maybe not... Ryan, you have created just about the best gift a web-developer can possibly ask for. Every day so many of us get to open this gift and create something new with it. Your gift compounds and expands exponentially as our work courses through the Internet and brightens the worlds of clients everywhere. ProcessWire helps make all of us bigger, faster, stronger... Not only have you created a great gift for us all, but personally you are a terrific presence: consistent, professional, helpful, patient, creative... In other words, HAPPY BIRTHDAY! Thanks, Matthew1 point
-
Nico, most of your clients seem to be pretty blurry, but that one fellow is exceptionally bright!1 point
-
Then you haven't studied the HelloWorld.module that comes as example? Hmm... it was the first thing I checked out when starting looking into modules and there's all examples also adding properties and methods. It's what definately blew my mind and made me stay with PW after all Edit: I don't mean to put you down or something was just wondering and I'm glad you found out now!1 point
-
You didn't knew this?! Where have you been?1 point