Leaderboard
Popular Content
Showing content with the highest reputation on 04/19/2015 in all areas
-
5 points
-
Thanks @interrobang, I have just committed an updated that takes care of your request. Now you can enter a mix of module class names for modules in the PW modules directory and URLs to module zip files for any modules only on Github or elsewhere. Should be a great addition.4 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_example3 points
-
Hi teo74, welcome to the forum You are sort of there with InputfieldPageListSelectMultiple - but alone, that is just one method of providing the visual input part of what you need. What you need is the Page fieldtype, which will give you the option of using Page List Select inputs, amongst others, in the backend. The Fieldtype is how the data is stored, formatted and linked internally, and the Inputfield is how this field is presented and manipulated in the backend by a user. Have a look at this video - Using the Page Fieldtype - to get an idea of how it all works. In summary: Create a new field (called 'related', perhaps?) using the Page fieldtype. Configure it for the types of pages you want to select, and how you want the selector to look (which Inputfield to use) Add it to the template where you want to choose related pages. Edit those pages and choose the related pages In those pages, you can get the related ones, and display the links, by doing something like this in the template code: <ul> <?php foreach ($page->related as $relatedPage) { echo "<li><a href='{$relatedPage->url}'>{$relatedPage->title}</a></li>"; } ?> </ul>3 points
-
Hey, as I often just copy someone else's (sometimes my own) modules structure as a starting point for a new module I thought there has to be a better way to archive that. That's why I created the "ProcessWire Module Generator": modules.pw If something missing? Or some more wishes for options or best practices? Let me know Here's a screenshot:2 points
-
This tutorial will outline how to create a membership system that requires account activation via email. If you have a decent understanding of ProcessWire it isn't difficult at all! Create additional fields By default ProcessWire has a name, email, and password field for the user template. To allow for account activation we will have to add a couple more fields. Create the following fields and add them to the systems default user template. You can make ProcessWire show the system templates by going to setup -> templates -> toggle the filter tab -> show system templates -> yes. user_real_name user_activation Okay great, now that you have added the two additional fields to the user template we can start to code the registration form. I am not going to spend a lot of time on this part, because there is a tutorial that describes creating forms via the API. Create the registration form Once you have followed the tutorial on creating forms, you will have to add a couple of sections to your new form! <?php include("./functions.php"); require("/phpmailer/class.phpmailer.php"); $out = ""; $errors = ""; //create form //full name field //email field //username field //password field //submit button //form submitted if($input->post->submit) { $form->processInput($input->post); //instantiate variables taking in the form data $full_name = $form->get("full-name")->value; .... /* * Create the activation code * You can add a random string onto the * the username variable to keep people * from cracking the hash * ex $activation = md5($username."processwire"); */ $activation = md5($username); $activation_code = $config->httpHost."/activation/?user=".$username."&hash=".$activation; //check for errors if($form->getErrors() || username_validation($username) == 0) { $out .= $form->render(); //process errors /* * this checks to makesure that no one has the username * I have a functions file that I import to the pages I * need it on */ if(strlen($username) != 0){ if(username_validation($username) == 0) { $username->error = " "; $errors .= "Sorry that username is already taken!"; } } } //the registration was successful else { $out = "Thank you for registering!<br><br>"; $out .= "An email has just been sent to " . $email . " with the url to activate your account"; /* * In this example I am using phpmailer to send the email * I prefer this, but you can also use the mail() function */ $mail = new PHPMailer(); $mail->IsHTML(true); $mail->From = "email@domain.com"; $mail->FromName = "Register @ Your Site"; $mail->AddAddress($email); $mail->AddReplyTo("email@domain.com","Register @ Your Site"); $mail->Subject = "Registration"; $mail->Body = " Hi " . $full_name. ", <br>" . "Thanks for registering at Your Site. To activate your email address click the link below! <br><br>" . "Activation Link: <a href='http://".$activation_code."'>".$activation_code."</a>"; $mail->send(); //create the new user $new_user = new User(); $new_user->of(false); $new_user->name = $username; $new_user->email = $email; $new_user->pass = $password; $new_user->addRole("guest"); $new_user->user_full_name = $full_name; $new_user->user_activation = $activation; $new_user->save(); $new_user->of(true); } } //form not submitted else { $out .= $form->render(); } ?> <h2>REGISTER</h2> <div class="errors"><?php echo $errors; ?></div> <?php echo $out; ?> Okay so that outlines the entire form. Let me get into the important parts. Checking for a unique username /* * check if username exists * return 1 username is valid * return 0 username is taken */ function username_validation($username) { $valid = 1; $check = wire("users")->get($username); if ($check->id) { $valid = 0; } return $valid; } We don't want to try and add a username if the username is already taken, so we need to make sure to validate it. If this returns 0 you should output that the username is already taken, and the user needs to choose a different one. Generating an activation code /* * Create the activation code */ $activation = md5($username); $activation_code = $config->httpHost."/activation/?user=".$username."&hash=".$activation; This generates an activation code. It does so by encrypting the username variable and then combines the username and activation code into a url for a user to visit. Now we have to process the activation code. As the teppo recommended, it is a good idea to add an extra string onto the $username when encrypting it with md5. If you don't do this, people may crack it and allow for mass signups. $activation = md5($username."Cech4tHe"); Activate the user <?php include("./head.inc"); include("./functions.php"); /* * this will pull the username and * activation code from the url * it is extremely important to * clean the string */ $activate_username = $sanitizer->text($_GET['user']); $activate_hash = $sanitizer->text($_GET['hash']); if(wire("users")->get($activate_username)->id) { if(strcmp(wire("users")->get($activate_username)->user_activation, $activate_hash) == 0 || wire("users")->get($activate_username)->user_activation == 0) { echo "Your account has been activated!<br><br>"; $activate_user = wire("users")->get($activate_username); $activate_user->of(false); $activate_user->user_activation = "0"; $activate_user->save(); } else { echo "There was an error activating your account! Please contact us!<br><br>"; } } else { echo "Sorry, but that we couldn't find your account in our database!<br><br>"; } include("./foot.inc"); This pulls the username and activation hash from the url. It then goes into the database and looks for the user. Once it finds the user, it get's the user_activation hash and compares it to the one in the URL. If it matches, it activates the user by setting user_activation to zero. Clean the url You can user the built in $sanitizer->text() method to clean the url. This will keep people from inserting special characters that can break the page. Keeping unactivated users out You aren't done yet! Now you will have to choose which areas you want to restrict to activated users only. An activated user's user_activation field will now equal zero. So if you want to restrict a section check to make sure it is zero...... if($user->user_activation != 0) { echo "Sorry, but you need to activate your account!"; } else { // activated users }2 points
-
since 2.5.24 OR-dependencies are possible: https://processwire.com/blog/posts/processwire-core-updates-2.5.24/#field-dependencies-upgrades2 points
-
Version Bump to 1.2.0 - Important Upgrade Destination Selectors Fix ProcessRedirects Importer (You can now also try the import again, if the previous import gets botched somehow) Various other enhancements and important fixes No schema changes2 points
-
Finally I have had time to download it. Its simply fantastic and a lot of fun! Regarding the windows users I share how I have set it up. Its only a bit slightly different than the very good explanation here from @marcus and @Mike_Anthony. I have done installation step 1 and 2, but not step 3. Instead of adding something to my path I simply created a single wireshell.bat file that I put somewhere into my already existing system path. I also have no PHP directory accessible through the system path, because I use minimum 5 different PHP versions (3 for CLI and 2 with the local Apache). If there were one in the system path this can lead to weird behavior of PHP, at least with the old PHP 4 that I need for older CLI tasks. My wireshell.bat looks like @ECHO OFF SET phpexe=C:\bin\php-54\php.exe SET phpparams=-c C:\bin\php-54\wireshell\ SET wireshell=%appdata%\Composer\vendor\wireshell\wireshell\wireshell TITLE WIRESHELL :: %CD% "%phpexe%" %phpparams% "%wireshell%" %* TITLE %CD% With the phpparam -c I have specified a directory where the php interpreter has to pickup its php.ini. I have one setup that is different than I need with other CLI scripts. I also could have linked to the php directory what is running under apache. But unfortunately I switch this between php 5.3.8 and 5.4.x for modules testing currently. (and composer and wireshell needs minimum 5.4.0) That with setting the title in the cli windows is nice if you have running several tasks. When hovering over the stacked icons on the taskbar, you can see which one is in "WIRESHELL mode" and which one is finished.2 points
-
Hi All, I am gladly posting my first site profile. Blue-VR Site Profile for ProcessWire Summary A site profile for corporate or personal website. Profile can be used with ProcessWire open source CMS/CMF version 2.3+. The front-end uses the Bootstrap 3.1 css framework for to get the responsiveness and mobile friendliness. Front-end Demo - bluevr.webcreate.lk Back-end Demo mode - bluevr-webcreate.lk/processwire (The username 'admin' and password 'bluevr2') Overall features * HTML5 & CSS3 + ({less}) * Build with bootstrap 3.1 * SEO Friendly * Clean & modern design * Responsive markup * Contact form and google map locations with multiple google markers * Testimonials using bxSlider * AIOM supports (Just install the module no need to touch the code) How to install Please take a copy of the latest ProcessWire (Replace the install, modules and templates directories with those in this profile, as shown below: - /site-default/install/ - /site-default/modules/ - /site-default/templates/ Make sure you do following steps as well 1. Add `tinymce` directory into /site-defaut. 2. Add the following two lines to your `/site/config.php` file: $config->prependTemplateFile = '_init.php'; $config->appendTemplateFile = '_main.php'; Download Github: https://github.com/gayanvirajith/BlueVrSiteProfile/ Credits I would like to thanks Ryan for giving us great CMS/CMF and modules. Hani AbuGhazaleh for a great module of Fieldtype: Select (AKA Drop Down) David Karich for providing such a nice module AIOM+. *** Please note that the site profile is still on testing stage. Thanks ------------------------------------------------------------------------ Edit: install instructions. Edit: Add credits Edit: Update live demo url Edit: Update back-end demo mode details1 point
-
Thanks for the site profile. This is golden! I will definitely try it in my next Bootstrap project (currently I'm more into Uikit).1 point
-
@Macrura Thanks - I'm glad you're liking it. Yeah, documentation is pretty important to me, and so I make sure I do it to the best of my ability. Originally, I wanted to host the documentation myself, but thought the GH wiki system would be perfect enough for the task. Regarding the selectors, I'm going to leave the implementation as-is for now (as mentioned in the docs).1 point
-
@Mike - this is really great, especially the new features; and a lot of care went into the documentation, and is much appreciated.. i hope others will find this useful! will be upgrading that site i was testing on and report back any issues.1 point
-
...and in the documentation as well: http://processwire.com/api/selectors/#or-groups Edit: sorry, this is a different matter; ignore my post...1 point
-
MuchDev does credit Soma though...but instead of re-posting the script, could have just linked to it1 point
-
Lars, use this search tool instead: Search for 'staging' OR 'moving'...etc...There's quite a number of discussions on this already1 point
-
I have read and re-read the first post so many times I was getting blind. I never saw the code under Checking for a unique username. With that included, I got it working. I should really read better on my own in the future! Thanks, cstevensjr, horst and pwFoo!1 point
-
Hhm, exactly what was posted 2 years ago here in the same thread by soma: https://processwire.com/talk/topic/3718-lots-of-images-to-resize-timeout-in-frontend/#entry362911 point
-
1 point
-
Before I merge, I'd actually like to discuss the behaviour of the new selectors feature. In its current state, you specify a selector in your destination path using square brackets ([[your-selector-goes-here]]). However, you can also use multiple selectors, and prepend and append to them, which I don't think it actually the right way to do it. Prepending a string to a selector will cause a redirect to a non-existent page. As such, I propose the following: Instead of using double-square brackets to return the URL of the new destination page (using $page->url), I think it should return the name. This is handy when you want to redirect /blog/2015/<oldname> to /journal/<newname>/, for example. Then, to return a full URL, we should use use find: as a prefix to the selector - find: template=basic-page, legacy_name={name}, for example. What do you think?1 point
-
This helped me with an install on Bluehost where I was getting a "Maximum execution time of 30 seconds exceeded" error from an image gallery (all of the images were small, around 800x800 pixels) I first changed PHP 5.4 (Blank or default) to PHP 5.4 (FastCGI) and the error went away for up to 10-20 images, but more than that and it came back. I added the line: foreach ($page->images as $image) { set_time_limit(30); etc...} This helped a little more but I was still getting the message when doing 30 images in one upload. Finally from this post: https://processwire.com/talk/topic/4280-best-server-configuration-for-processwire/?p=42081 I decided to change the php.ini settings: memory_limit to 256M post_max_size = 100M memory_limit = 256M upload_max_filesize = 100M max_file_uploads = 100 I didn't bother changing : "max_execution_time = 30" since I figured that the above code would take care of that, 30 per file, instead of the whole script. It seems to be working fine now, atleast with 30 - 50 images uploaded at once.1 point
-
I realised that although this successfully displayed my form, it wouldn't help my client. Anything they edit and FTP into /templates/includes/ still wouldn't be reflected in /site/cache/HannaCode The suggestion by @Macrura (and probably @LostKobrakai) worked out in the end.1 point
-
I couldn't agree more with Apeisa here. It comes down to a choice: if you want ProcessWire to become popular outside of that group of traditional developer types then you have to appeal to those with 30 minutes to spare and low technical experience. If on the other hand people here are happy to let ProcessWire grow slowly, organically, continually appealing to more technical mindsets then it is doing a great job already and should simply continue on that path. There is nothing wrong with either route and it all comes down to the expectations of the community here. One word of warning about expectations though. I watched the Drupal community grow from version 5, 6, 7 onwards and the bitterness that resulted within the community when WordPress started to dominate the market (around Drupal 6) was palpable. The Drupal community believed that they had a far better system with more flexibility and inherent security, but they were very scathing of the fact that WordPress (sometimes described as 'HerdPress' within the Drupal community) became so popular and Drupal didn't. My point (eventually) is that until very recently (with the advent of Drupal 8) the Drupal community missed the reason as to WHY WordPress was dominating so. They thought it was marketing, but really, it wasn't. The simple reason was that Drupal was engineered for developers and encouraged very little involvement from the design community. I couldn't count the amount of times designers would attempt to engage in the forums and request a simpler theming system only to be sounded out by the developers there - sometimes very aggressively. WordPress on the other hand encouraged the design community and became easy enough for designers with traditional design mindsets to pick up. WordPress actively engaged that audience and a theming system was built that partially catered towards them. Combine the WordPress theming system and an admin interface which is one of the nicer ones to look at and use and you have a package that appeals very strongly to a lesser technical mindset. The whole concept of growth and whether to cater towards the less technical mindset then comes down to choice and expectations. If ProcessWire continues down its current path, it will build a very strong following of developers (and some slightly more technically minded designers). However, it will never grow beyond a certain scale and will always be less popular than many other choices already out there. Again, that's okay if the intention is there to focus on that audience to the exclusion of others. However, the market out there for the designer / CMS administrator type of profile is vast and much larger than that of a development centric audience. It's a simple truth and one which would need to be catered for with better turnkey solutions if ProcessWire wanted to better engage the non technical mindset. The community would also need to welcome them (which I don't think will be a problem from my experience). If ProcessWire wanted to engage and grow its audience to compete with the 'bigger' and more popular systems it's already (in my opinion) in a much better place than Drupal to capture a less technical market. It's API is streets ahead in terms of simplicity for frontend development and it's community is less hardcore. However, some things need to be more readily available to cater towards the designer type who isn't a frontend specialist. A theming system is central to that need (again, in my opinion). The traditional designer mentality is one that is only very slowly moving in a more technical direction (in a typical sense). The Photoshop GUI and knowledge of CSS being as technical as it gets for that type of user. Therefore, having pre-built examples and tools that are easy for a designer to iterate on are essential. Having a packageable theming system would not only help others coming from other systems with ProcessWire, but would enable designers to have less complex starting point to suite different needs. I work with a number of designers coming out of university who still have poor technical skills, they barely know Photoshop to the level that is needed. ProcessWire is unfortunately too great a step for them. Whereas WordPress is easy for them to pick up. In WP they can install a theming base and then iterate from that quickly, they also have plenty of how-to guides catering towards their mindset. Most of the time, they will use a theme base as a starting point for their PHP and XHTML markup and CSS, completely altering the CSS and some of the XHTML, but barely touching the PHP 'voodoo'. However, after a few months they start to become more comfortable with PHP and will then iterate on that layer as well. Then, a frontend developer starts to emerge! They are now very comfortable with WordPress because they have had success with it. Nico's solution I think is perfect for the ProcessWire community. Simple, elegant, potentially very powerful and more importantly optional. When this reaches maturity, you could combine this with a series of tutorials and profiles engineered towards a designer mindset and you have a very simple way to better engage that type of audience and attract them to the ProcessWire project. As a by product of catering for that designer mindset, you then also have the potential turnkey solutions that an even larger audience profile thirst for...1 point
-
Too simple to be a module, consider a script like this: $array = $pages->find("template=basic-page")->explode(function($item){ return array( 'id'=> $item->id, 'title' => $item->title ); }); $fp = fopen('file.csv', 'w'); foreach ($array as $fields) fputcsv($fp, $fields); fclose($fp); Note, $pagearray->explode() used here is only available in 2.4 (2.3 dev) http://cheatsheet.processwire.com/pagearray-wirearray/getting-items/a-explode/ And the anonymous functions requires php >= 5.3 http://php.net/manual/de/functions.anonymous.php1 point