Leaderboard
Popular Content
Showing content with the highest reputation on 09/16/2013 in all areas
-
Hi everyone, The new website of my company Omnitic is finally launched! Initially started in Wordpress, it was finally built on Processwire with Gumby Framework as i wanted a real use case to practice my "wiring". I must say that i'm pleased with the final result and how fast it was to get this up and running with Processwire. For a extra speed boost ProCache has also been used to make the overall experience as fast as possible : if you build website with Processwire and don't use this module, you're doing it wrong. There's still some tweaking to be done though (image optimization, some responsive issues to name a few) Regards and happy wiring. Nicolas9 points
-
Here's an example of the performance boost I gained by doing this... My page was 26kb before, and 4kb after. Page loading time was reduced by almost half. In site/config.php uncomment $config->prependTemplateFile and $config->appendTemplateFile = '_out.php'; /** * prependTemplateFile: PHP file in /site/templates/ that will be loaded before each page's template file * * Uncomment and edit to enable. * */ $config->prependTemplateFile = '_in.php'; //you can name this file whatever you want /** * appendTemplateFile: PHP file in /site/templates/ that will be loaded after each page's template file * * Uncomment and edit to enable. * */ $config->appendTemplateFile = '_out.php'; //you can name this file whatever you want Create two new files in site/templates called _in.php and _out.php. In _in.php add the following at the top of the file (before any code that you add later) <?php if (!in_array('ob_gzhandler', ob_list_handlers())) { ob_start('ob_gzhandler'); } else { ob_start(); } ?> In _out.php add the following at the bottom (after any code you add later) <?php ob_end_flush(); ?>6 points
-
As mentioned, you can achieve this via re-categorisation of your pages or via URL segments. A similar question was asked last week. See the thread linked below and especially Ryan's response for an alternative method using hooks. http://processwire.com/talk/topic/1973-url-shortener/?p=442114 points
-
I would use the config options in site/config.php for including functions (ver. 2.2.3+ i think, maybe it's 2.3+)... /** * prependTemplateFile: PHP file in /site/templates/ that will be loaded before each page's template file * * Uncomment and edit to enable. * */ $config->prependTemplateFile = '_in.php'; /** * appendTemplateFile: PHP file in /site/templates/ that will be loaded after each page's template file * * Uncomment and edit to enable. * */ $config->appendTemplateFile = '_out.php'; In _in.php you can set up things that need to happen for each template. The nice thing about this option is not having to use an include statement on each of your template files. In my _in.php example below I'm initializing fredi and including functions. That's about all I'm using _in.php for. $fredi = $modules->get("Fredi"); include("./includes/functions.php"); Your approach is a nice one. You could also wrap ob_start around all output and gzip it. PW may already do the gzipping, I don't know. //compress the output for faster page loads ob_start("ob_gzhandler"); //output from your includes needs to be sent back with a return //e.g. return $html_string; or return $data as an array $body[] = include './teaser.php'; $body[] = include './pager.php'; $page->body = implode("\n",$body); //you can also use file_get_contents on a public url //(but you'll need to bootstrap PW if you need access to $page,$pages, etc.) //e.g. file_get_contents('http://www.mysite.com/my_php_include.php'); //depending on needs, maybe easier just to... //include './teaser.php'; //include './pager.php'; //$page->body = ob_get_contents(); //ob_clean include './main.php'; ob_get_clean(); Here's what the contents of teaser.php could look like... //this gives you some flexibility to format data as you wish and is helpful if you want agnostic data //you can also use this approach to create your own template system. (e.g. regex replacement {{body}} with $page->body) switch ($input->urlSegment1) { case "csv": //format data for cvs, save to file, provide download link break; case "xml": //format data for xml break; default: //format data for html foreach ($page->children as $a) { $data[] = "<li><a href=\"#{$a->$name}\">{$a->title}</a></li>"; } return "<ul>" . implode("\n",$data) . "</ul>"; } And while you are at it, maybe the better approach is to put ob_start("ob_gzhandler"); in _in.php and ob_get_clean(); in _out.php. Really just depends on what you want to do, but you can see how damn cool PW is.3 points
-
Good job! Thanks for the tip. Please note, people, that before implementing this you must check your PHP zlib configuration. Because the official PHP documentation states that To check, either run php -i | grep zlib.output_compression if you are on a console, or do the usual phpinfo() thing and search for zlib.output_compression. To note the obvious: if you are using PW 2.3.0, the default file names are: $config->prependTemplateFile = '_init.php'; and $config->appendTemplateFile = '_done.php'; With the almost untouched default site profile, I got 34 kbytes without uncompression vs 8 kbytes with compression (page /about/; traffic measured with Comodo Dragon (based on Chromium). Screenshots are attached). One last remark: the PHP docs recommend turning on zlib.output_compression. Which is understandable once you start taking PW caching into account.2 points
-
2 points
-
Would this makes sense or even easy possible to add a property, so you could simply check in moules/templates if you're in admin or frontend using: $config->isAdmin; Something like the $config->isAjax; If not, so those are the common checks that can be used to determine this (for reference): if( wire("page")->template == 'admin' ) { // is in admin } if( wire("page")->template != 'admin' ) { // is frontend } if( strpos( $_SERVER['REQUEST_URI'], wire('config')->urls->admin) !== false ) { // in admin } checking for only certain admin processes or areas is also possible // in a autoload module you could also use if( wire("process") == 'ProcessPageEdit' ) { // is editing page } if( strpos( $_SERVER['REQUEST_URI'], wire('config')->urls->admin . 'page/edit' ) !== false ) { // in editing page }1 point
-
The Organization of American Historians just converted its website to Processwire: http://www.oah.org/ Founded in 1907 and with its headquarters located in Bloomington, Indiana, the OAH is the largest professional society dedicated to the teaching and study of American history. — Michael Regoli, OAH1 point
-
Hi there, well, a few days ago another project of mine went online. I did that homepage for a local voluntary firefighters' club with a friend of mine at the front. My job was to create the technical basement. I used the 960 Grid System framework to do the design and implemented the base templates, my friend created an interface to synchronize the homepage calendar with a firefighters' organizational software he programmed on his own and also did some optical tweaks, Piwik integration and content. http://www.feuerwehr-friedrichshofen.de/ Regards Seuche1 point
-
If you enable URL segments on the home page you could get what you want. Or you could create the rootParent catering and do your search there.1 point
-
Looks like spellcheck no longer works. I've got some obvious ones in there but it fails to find any errors and continually says "no misspellings found"1 point
-
Here's another bit of code from Ryan that might prove helpful: http://processwire.com/talk/topic/3299-ability-to-define-convention-for-image-and-file-upload-names/?p=32623 It is not for random filenames, but it does show how to set up a file renaming module1 point
-
I like this site - nice and clean and modern. Good work! I've been meaning to try out Gumby at some point as well so will have to find time (like that ever happens ).1 point
-
Do you want to rename the original files on upload? If yes, here are some pieces of code I have collected in the forum from Soma. This could be a starting point for a module: <?php class ImageRenameOnUpload extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'ImageRenameOnUpload', 'version' => 100, 'summary' => '', 'href' => '', 'singular' => true, 'autoload' => true ); } public function init() { $this->addHookBefore('InputfieldFile::fileAdded', $this, 'renameImage'); } public function renameImage($event) { $inputfield = $event->object; if($inputfield->name != 'images') return; // we assume images field !! name of the field is: images !! otherwise change it $p = $inputfield->value['page']; // get the page $image = $event->argumentsByName("pagefile"); // get the image $ext = $image->ext; // get extension $newBasename = 'my_random_name_' . time(); // create your random name here !! $p->images->trackChange("basename"); // prepare page to keep track for changes on basename //$image->removeVariations(); // isn't needed here, I think $image->rename($newBasename . '.' . $ext); // rename the image $p->save('images'); // save the page } } As of this code will work, you have to add something that refreshs your admin page at the end, because upload is via ajax request and the label presenting your imagefilename isn't updated now. But should be a good starting point. EDIT: Have changed addHookAfter to addHookBefore and then it all works, including updating the label with filename! Don't know really why in detail. Just have found out by trying!1 point
-
Don't know why, I tried everything again right now and it works, thanks anyway1 point
-
No, the fastest way is echo '<a href="'.$pages->get(2)->url.'">this way to the admin</a>';1 point
-
I'm using this feature quite a lot. Here's an example of creating a indented list for using with checkboxes, selects. IT creates a new PageArray and modifies the "title" to indent, and here with a (count) used in the context of the categories to see how many products are under that category. $children = $pages->get("/shop/")->children(); $list = new PageArray(); function mylist($children, $ind='', $arr){ $ind .= "– "; foreach($children as $cat) { $countproducts = wire("pages")->find("template=product,categories=$cat")->count(); $cat->title = $ind . $cat->title . " ($countproducts)"; $arr->add($cat); if($cat->numChildren) { mylist($cat->children,$ind, $arr); } } return $arr; } return mylist($children, $ind='',$list); This will produce something like –– Gewürze (0) –– –– Kräuter (27) –– –– Kräutermischungen (7) –– –– Einzelgewürze (0) –– –– –– Anis (2) –– –– –– Blaumohnsaat (1) –– –– –– Bockshornsamen (2) –– –– –– Chili (16) –– –– –– Glutamat (1) –– –– –– Galgantwurzel (3) –– –– –– Ingwer (4) –– –– –– Kardamom (4) –– –– –– Knoblauch (5) –– –– –– Koriander (2) –– –– –– Kurkuma (2)1 point
-
Since you are comfortable with using the MVC pattern, this may be the way you want to go in ProcessWire too. ProcessWire is very much supportive of the MVC pattern, it's just that it doesn't require it. ProcessWire is providing your models, your template files provide your controllers, and you provide the views with the TemplateFile class (or some other view loader of your own if preferred). You can also choose to target some template files/pages as views and call $page->render() on them. If you are interested, the Blog profile does use an MVC-style approach and would be worth looking at. But after you spend some time with ProcessWire, I recommend finding the approach that best suits a particular situation rather than locking yourself down to using the same one all the time. ProcessWire is giving you a lot more in some areas than a typical MVC framework does, so you may find even faster and more maintainable ways to structure your code, depending on the situation.1 point
-
Uhh, I have a lot do to right now. But if I have any free time in the next days this is the first thing I'll continue1 point
-
It might be feasible to do something like Soma's function above, where it populates the old (valid) value back when an invalid value is received. But rather than throwing out the old value, remember it a session variable. Then your module would also hook after ProcessPageEdit::buildForm and cycle through the any saved session variables, populating back the values it recorded (and removing them from the session). It's necessary to use session variables here just because there is a redirect between saving an editing again, something that is not obvious when you are using PW to edit pages. I would recommend something like: $values = array( 123 => array( // indexed by page_id 'date_from' => 'October 33, 2013', // invalid date 'body' => 'some bad words here', // invalid value ); $session->set('PageEditBadValues', $values); Also wanted to recommend hooking ProcessPageEdit::processInput rather than InputfieldForm::processInput, just so that you are limiting the action to the PageEdit form and not getting involved with other InputfieldForms unnecessarily. Your after(ProcessPageEdit::buildForm) function might look like this: function hookPageEditBuildForm($event) { $form = $event->arguments(0); $page = $event->object->getPage(); $values = $this->session->PageEditBadValues; if(empty($values) || empty($values[$page->id])) return; $values = $values[$page->id]; foreach($values as $fieldName => $value) { $inputfield = $form->getChildByName($fieldName); if(!$inputfield) continue; $inputfield->attr('value', $value); } }1 point
-
Can you describe your scenario? Here's a common scenario: Lets say you've got a section called /articles/ and you want to have authors that can edit articles: 1. Create new role called "author" and check permission box for "View" and "Edit". Assign this role to one or more users you've created. 2. Edit your "Article" template (Setup > Templates > edit), the one represented by /articles/some-article/, etc. 3. Check the "yes" box on "access" tab to enable access control. 4. Next to the "author" role, check boxes for: View, Edit Want your authors to be able to create new articles too? 1. Edit your "Article" template again, check the box for "Create" for the author role. 2. Edit your "Articles" template (the one represented by page /articles/). Enable access control and check the box for "Add Children" for the author role. Want authors to only be able to create new articles but not to publish them? 1. Add a new permission (Access > Permissions > New) and call it "page-publish" 2. You don't have to do anything else. Since the author role doesn't have page-publish permission, they can't publish pages. They can still edit and create unpublished pages. Tell me more about your scenario and I'll outline instructions.1 point
-
Sevarf2, you are correct about something here in that theoretically, supplying the template to the find() call should enable it to run faster. ProcessWire needs to know the template for a page before it starts loading it. So it'll query the DB for the page's template if it doesn't already know it. However, we don't have that optimization in place for $pages->find() at present, so your $pages->get("id=123, template=book"); doesn't benefit from that. But you can take advantage of that optimization by using the $pages->getById() method. It would technically be the fastest way to retrieve a page, but it's rare that I would be up for using it when developing a site (I only use it for core development). But it may be worth trying if you are trying to optimize a large amount of page retrievals. I'm not sure it'll make much difference in the end, but it's worth a shot. $template = $templates->get('book'); $page = $pages->getById($page_id, $template)->first(); The getById() method is really meant for retrieving multiple pages, which is why it returns a PageArray. If you have multiple pages using the same template, you can retrieve all of them here: $pageArray = $pages->getById(array(123,456,789), $template); If you can also supply a parent_id to the method (meaning, you already know all the provided page IDs have the same template and parent), it can use that for a little further optimization: $pageArray = $pages->getById(array(123,45,789), $template, $parent_id); Btw, the purpose of $pages->getById() method is as a support for all the other get(), find() and children() methods in ProcessWire (or anything else that returns a Page or PageArray from the DB). All pages loaded from the database are loaded by the getById() method, so all the other get/find methods are actually front-ends to it. getById() was never intended to be part of the public API though.1 point
-
Currently it gives me an error: Parse error: syntax error, unexpected '[' in /.../site/modules/ProcessPageTreeMigrator/ProcessPageTreeMigrator.module on line 666 And the code there is: $newArray = []; So it requires php 5.4. Just changed it to array() and now it works. Importing full data still doesn't work, this time it seems to be repeaters: FieldtypeRepeater: Created Repeater Page Parent: /processwire/repeaters/for-field-98/for-page-1067/ TemplateFile: Method RepeaterPageArray::setLanguageValue does not exist or is not callable in this context For me export & import of templates and fields is the main selling point of this module (not the data).1 point
-
1 point
-
Excellent information. I too have just successfully installed Processwire on Windows Server 2008 running IIS 7. Thanks to everybody posting on this page. Extra information from my situation in case somebody else is running into similar issues. I had never even heard of this CMS until I was told I needed to install it to host a web site for a subsidiary. I had previously installed PHP and MySQL on the system and really didn't feel like installing Apache if I didn't need to do so. I took a leap of faith after reading on the Requirements page that "A user has reported that that were able to install ProcessWire on IIS 7 in Windows 7." Issues and Resolutions Rename /site-default to /site The files you download for Processwire include the folder "site-default", just rename the folder as requested. I was looking to see how IIS interpreted the default web site and was confused immediately. It's a real simple request when you know what it means. Error 500 reported within the browser Immediately I got the 500 error in the browser. That didn't mean much to me so I executed the PHP script from command line. Open a command prompt and navigate to the directory in which you are installing Processwire type full path to php.exe or php-cgi.exe and then install.php e.g. C:\myphpfolder\php.exe install.php This will report the error generated in the script and not just the generic 500 error. In my case PW could not find MySQL on the host. Error 2002 No such host is known (Database connection error) I did a bunch of searching for this. The error actually occurred in the /wire/core/ProcessWire.php file. In review of the code I realized it was parsing the page location to find the "localhost" name. In my case I was not using the default website and I had another name not recognized by (I assume) the hosts file (C:\Windows\System32\drivers\etc). After thinking about it now, I could have probably added the name I had in the hosts file. My resolution was to "Add Application" within the Default Website in IIS pointing to the install location. Now localhost is a valid host name and MySQL could be located. Error 404 file or folder The Processwire home page was fine, but no sub-directory calls worked. That's when I found this post. I took nikola's suggestion: "Download URL Rewrite Module 2.0 for IIS from http://www.iis.net/download/urlrewrite and install it" I downloaded the web.config file he provided and placed it in the Processwire root I removed the <add sequence="module" /> entry as stated by jamestflynn Then finally incorporated the suggestions by zlojkashtan as I understood why that would be important The default site is running. The URL rewrites are working. You guys are awesome.1 point
-
@sitnarf - you mean like this? http://processwire.com/talk/topic/704-datatable/?p=406211 point
-
This is the nature of how the ajax uploading works, as it triggers a page save (though saving only the field you upload to). One way we could solve it is to add a status field to the file/image fieldtypes, giving them a way to identify a file as unpublished. Not sure how simple it will be to implement, but this is one of the things I've had on my list for awhile. If it comes up more often, I'll definitely bump it higher up the priority list.1 point
-
First of all, create a template called "tags". It is totally fine to leave as it is, just a "title" field, no need for a PHP-file (for now). To be sure, only allow children with template "tags" in the template "family" tab. Then create your hidden "tags" page. Put same tags in it (that means: create children pages with your tags as title) if you like. Correct. Template for selectable pages is "tags". You can also define your hidden tags page as parent. No template file needed (for now). Not necessarily. or from the page select field itself (very convenient). So for that you need to have a .php file as template for the template "tags". First, create your tag list like this: echo "<ul>"; foreach($pages->get('/tags/') as $tag){ //iterate over each tag echo "<li><a href='{$tag->url}'>{$tag->title}</a></li>"; // and generate link to that page } echo "</ul>"; (totally untested, but you'll get it). Since the tag pages have no template yet, this will throw an empty page (or 404, don't know). So let us create a template for the tag pages, which lists all pages with that tag: // Beginning of your template here (head etc.) // select all pages with the tag of this tag page $thisTag = $page->title // Current clicked tag $tagPages = $pages->find("Tags.title=$thisTag"); // select all pages where page field "Tags" contains a page with title of our tag foreach ($tagPages as $tp){ // iterate over the pages with that tag // and generate some teasers (or what you like) echo " <div class='teaser'> <h3>{$tp->title}</h3> <p>{$tp->summary}</p> <a href='{$tp->url}'>Read more...</a> </div>"; } // Rest of your template here (footer, javascripts etc.) as I said, totally untested, but this should point you in the right direction.1 point
-
The error message doesn't look like a problem with the host to me... maybe there was some problem when copying or unzipping the files? edit: just noticed that this was my thousandth post1 point
-
That makes sense to me. To add to your list of ways to check, here's another that should be pretty bulletproof: if(strpos($page->url, wire('config')->urls->admin) === 0) { /* hello admin */ }1 point