Leaderboard
Popular Content
Showing content with the highest reputation on 08/25/2015 in all areas
-
ProcessSlider Module (alpha version) Repository https://github.com/mauricius/ProcessSlider Introduction Like many of you, I came to ProcessWire from Wordpress and immediately I fell in love with its power and its clean syntax. I have to say that PW has become my default choice for building websites. However there is only one thing that me and my clients miss from WordPress and is the ability to visually build image sliders through plugins (Nivo, Revolution Slider, LayerSlider, just to name a few). So I decided to create a module for this purpose. ProcessSlider essentialy is an editor for the wonderful Jssor plugin (http://www.jssor.com/) which is absolutely free. The module creates a new page under the Setup menu which allows users to easily add image sliders on the site using an intuitive visual editor. To each slider you can easily add images and other custom and animate them using the transition effects provided by the Jssor slider. The ProcessSlider module in reality is composed by three different modules: ProcessSlider: the main module InputfieldSlider/FieldtypeSlide: allows the user to use an existing slider inside a page MarkupSlider: converts the slider into Jssor compatible markup and optionally provides the necessary initialization script Features Custom slider size Drag and Drop interface Move and resize elements Slides background with images from existing PW pages Slider Preview (with the provided MarkupSlider module) Predefined style classes for Elements Add or remove Slides Add or remove elements Change slide order visually Jssor skins and bullets support Visual Timeline Optional responsive/fullwidth slider Predefined elements: Images, Text, Links, Image as link, Div blocks, Youtube Videos Animation Options (In and Out): Animation type, Delay, Duration The editor is built with Vue.js+Webpack and uses jQuery for D&D and resize functionalities. Release I'm going to release the module in a couple of weeks, there are still some minor tweaks and improvements that I would like to add. Demo Screencast (be sure to watch it at least at 720p) I hope it will be helpful to the community and I would be glad to get feedback or suggestions for improvement! Please also consider that it is my first PW module, so probably I'm missing some best practices, hopefully the most experienced developers can throw me some hints11 points
-
I just attended one of the free A List Apart live-events and was quite amazed. The big topics that were discussed were how to chose a cms, evaluating not only the frontend, but also the author/backend user experience and workflow needs and finally the current interest in decoupled cm-systems. The great thing was, that on all of those topics I was constantly thinking how nice it is to handle these things in PW. Some may include more work than others, but in the end it's really avoiding lots of those mentioned difficulties / roadblocks with cmss. So my conclusion is really "I love my CMS" . For the curious I've included the link to the event page, where the hangout/transscript will be posted later and the hangout link, so you can watch it as long as the event page isn't updated. Maybe someone did even watch it live as well. http://alistapart.com/event/content-management https://plus.google.com/events/clcdcbjo5puojn47aprk5plkem0?authkey=CMP6kImisby_tgE9 points
-
My second site done with PW! Fairly simple site though http://sensoriaoficial.com It uses Multi Language modules and a small module found at the forums (and later here) to set the home page to a specific language. And what I love most about PW, a straightforward one page admin for my client to edit their texts, add images to slider. change music file. Can't get any easier!6 points
-
Good work! Regarding best practises, the only suggestion I have is that the tutorial should be changed to use environment variables for the database connection. This has several benefits, for an example It would be very easy to launch a separate development site, which uses a different database, because all you need to change is the environment variable when launching the development web container You could easily use the same config.php as a template for new sites You don't have to store sensitive information in your version control The config.php becomes more cloud compatible (i.e. a twelve-factor app) Also since the MySQL-container is linked to the web-container, the config.php can directly use the environment variables set by Docker. An example config.php would be $config->dbHost = getenv("MYSQL_PORT_3306_TCP_ADDR"); $config->dbName = getenv("MYSQL_DBNAME"); $config->dbUser = getenv("MYSQL_DBUSER"); $config->dbPass = getenv("MYSQL_DBPASS"); $config->dbPort = getenv("MYSQL_PORT_3306_TCP_PORT"); Obviously launching the web container(s) would need to include these variables too, e.g. docker run -e "MYSQL_DBNAME=mypwdb" -e "MYSQL_DBUSER=mypwdbuser" -e "MYSQL_DBPASS=mypwdbpass" --name celedev-site -p 8088:80 --link database:mysql --volumes-from celedev-data -d php-5.6-pw-celedev Just my two cents3 points
-
Just checked in a first beta version of a new module I'm working on. Feel free to test out and see what's up with it. Pollino (beta) A simple poll module for ProcessWire This module makes it simple to setup polls for your website. It is based on a simple page setup to create the polls. So each poll is a page, and its children are the answers. Pollino will create the templates and a PollinoPolls page in the root to start with. You can add fields to the templates as you wish and later use hooks to modify the output of the poll. This can be useful, for example, to use images as options or just some custom markup etc. It provides some API to render the poll form and the result. These methods are hookable and it's easy to customize the output if needed. It can be rendered on any page and even multiple on the same page. Pollino takes care of saving the votes and preventing multiple votes. It comes with some configuration settings to choose what method to use to prevent from multiple votings: using cookie and an expire time or by IP and optionally also the UserAgent with and expire time or by logged in User Pollino isn't 100% plug'n'play but it provides a solid foundation and comes with some premade theme and output for you to start. It takes care of the boring stuff and lets you concentrate on the front-end stuff and styling. That's what matters after all. It does support multilanguage, as all strings are translatable in the module. Also since it's using simple pages and templates you're free to add or change fields to make its output multilanguage without much hassle. ----- Read more and download https://github.com/somatonic/Pollino Online Demo I setup a little demo here to see using https://lightning.pw http://titanium-x77.lightningpw.com/ Have fun.2 points
-
Hi, I just wanted to sing a song of praise of how smart actually PW is (designed). From my recent posts here in the forum you may know what I'm currently trying to do in my spare time - I port/migrate a fairly popular handbuilt 16 year old forum over to process wire. Reason is; the forum's users have grown to like the not-like-the forums out there look of the 16 year old originally perl/cgi based thing, which basically is nothing else like a nested list in most views, which then got enhanced whith loads of custom pages, functions, galleries and wutnot. 16yrs worth of procedural php code, created by at least 4 different and differently skilled developers. Bring it on! Whatever the reason, I thought this might be the perfect pet project to get to know PW in and out. And I really have to say: I'm deeply impressed. I have over 15 years experience wiith different CMSses, and I consider myself as fairly skilled in TYPO3 (yes, with that Typoscript riddles), know my way around cutsomizing and theming Wordpress sites since wp2.1 and I messed around with several other popular and not so popular CMSs as a part of my daily work. For like 1.5 years now I use PW as the "motor" of most sites I build. And now, with this "pet project" of mine, I'm really starting to fall in love : Being able to bootstrap the API and creating scripts that I can "fire" via the commandline, directly on the server, connecting to other databases, helped immensly with the task of getting 186000 posts by 5000 users into a processwire install. creating the relations between these posts (which one is the root of a "discussion", what is the "parent" of the current post) was easily done be using "Page" fields and again a script that scraped that info from the old structure and populated the page fields accordingly. I plan to write a detailed how-to once the migration is completed and working, but this could take some time ;-) Now the backend would time out if I wanted to edit one of the post. Caching the templates didn't help, so I thought about what was going on "under the hood" -- and after a little bit of head scratching it occured to me that maybe the 4 "Pages" field each post carried, were to blame, esp. the 2 fields referencing the whole collection of posts: "post_root" and "post_parent" -- each of which could theoretically be one of the other 185999 posts in the database. Since the default option for the visibility of "pages" fields are "select" and "open", PW needs to query the 185999 posts - and that brought down my php script execution limit and/or the allocated memory size of 152MB. Wow. But guess what, and that's where my romance with PW started for real: If you switch the visibility to "closed", or in my case to "closed with ajax on opening" the backend will run fast again. Now the selects will only be populated (with ajax) if I need to change the post_root or post-parent - which should never be necessary in the everyday use of that data. Initially I had imported the 4000 users not with the system's user template, but a custom one. While this worked without a problem, it brought down the lister, which wouldn't respond and time out after like 5 minutes. I still don't know why, but changing those users to the system user template got rid of that problem, and now they are behaving quite well. This is so cool. What started as a late night idea seems now to grow into a real project. With all that importing and moving imported data to pages data, I had like half a million pages in this install, and PW handled this quite nicely. In the meantime I have cleaned up and currently I'm down to about 186000 pages plus 4000 users plus some static pages. This wouldn't have been possible without the option to use the PW API from the outside. Thank you Ryan for this great piece of software. Cheers, Tom1 point
-
Docker (http://www.docker.com) is an open platform for building, shipping and running distributed applications. Docker containers are a great way to package a complete application with its specific dependencies in a portable way so that it can easily be deployed on any compatible network or cloud infrastructure. Recently I spent a few days making my ProcessWire site run in a Docker container, and - as I could not find any good tutorial for this - it sounded like a good idea to write one. You will find on the web plenty of presentations and tutorials about Docker, so I won't start with the basic concepts, and this tuto assumes that you have a first understanding of Docker's fundamentals. What we want to do here is to migrate an existing site to a set of docker containers. Therefore, to start with, you should have: - docker installed on your computer; - the site directory of your ProcessWIre site - a backup of your site's MySQL database Let's start. Create a docker container for the site database For several reasons (insulation, security, scalability), it is preferable to host the site database in a separate docker container. 1. Set-up a SQL database with MariaDb or MySQL $ docker run --name database -e MYSQL_ROOT_PASSWORD=rootdbpassword -d mariadb Here I choose to use the MariaDB official container in its latest version, but MySQLwould be just fine as well. 2. Run a PhpMyAdmin container and create the ProcessWire database We first select an simple image with PhpMyAdmin on the Docker Hub: nazarpc/phpmyadmin and we create a docker container based on this image. This container will access the port exposed by the database container via a private networking interface. We specify this with the `--link` option. It can be run temporarily (and exited by ctrl-C): docker run --rm --link database:mysql -p 8881:80 nazarpc/phpmyadmin Or it can be run as a daemon in the background: docker run -d --name phpmyadmin --link database:mysql -p 8881:80 nazarpc/phpmyadmin From phpmyadmin (accessed from your browser at http://hostaddress:8881) you can now create your ProcessWire database, create a dedicated user for it, and import the database content from a previously saved SQL file. Note: alternatively, you can do all database operations from the command line in the database docker container created during step 1, or use another mysql user interface container if you prefer… 3. Update the database parameters in your site configuration In your site's `config.php` file, the sql server name shall be set to `mysql`: $config->dbHost = 'mysql'; Other `$config->dbXxx` settings shall match the database name, user and password of the just-created database. Create a Docker Image for Apache, PHP and the Processwire site 1. Create an image-specific directory with the following contents and `cd` to it bash-3.2$ ls -l . config .: total 16 -rw-rw-rw- 1 jean-luc staff 1163 21 aoû 12:09 Dockerfile drwxr-xr-x 17 jean-luc staff 578 17 aoû 12:48 ProcessWire drwxr-xr-x 7 jean-luc staff 238 21 aoû 12:07 config drwxr-xr-x 7 jean-luc staff 238 20 aoû 18:46 site config: total 160 -rw-rw-rw- 1 jean-luc staff 160 20 aoû 18:28 msmtprc -rw-rw-rw- 1 jean-luc staff 72518 20 aoû 18:56 php.ini where: `ProcessWire` contains the version of ProcessWire that we want to use for this site; It can be retrieved from github with a link like https://github.com/ryancramerdesign/ProcessWire/archive/{version}.zip` For example, the 2.6.13 dev version can be obtained by the link https://github.com/ryancramerdesign/ProcessWire/archive/7d37db8d6b4ca6a132e50aff496a70e48fcd2284.zip `site`: our site-specific files `Dockerfile`: the dockerfile for building the image (see below) `config`: a directory containing specific configuration files copied to the docker image (see below) 2. Set the `Dockerfile` content FROM php:5.6-apache RUN apt-get update \ && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev libpng12-dev zziplib-bin msmtp\ && a2enmod rewrite \ && a2enmod ssl \ && docker-php-ext-install mysqli pdo_mysql iconv mcrypt zip \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ && docker-php-ext-install gd EXPOSE 80 EXPOSE 443 # Add a specific php.ini file COPY config/php.ini /usr/local/etc/php/ # Configure the mail sent utility msmtp (http://msmtp.sourceforge.net) and make it readable only by www-data COPY config/msmtprc /usr/local/etc/php/ RUN chmod 600 /usr/local/etc/php/msmtprc \ && chown www-data:www-data /usr/local/etc/php/msmtprc # Remove all default site files in /var/www/html RUN rm -fR /var/www/html/* # Copy ProcessWire core files COPY ProcessWire/wire /var/www/html/wire COPY ProcessWire/index.php /var/www/html/index.php COPY ProcessWire/htaccess.txt /var/www/html/.htaccess # Copy site-specific files COPY site /var/www/html/site # Make www-data the owner of site-specific files RUN chown -R www-data:www-data /var/www/html/site VOLUME /var/www/html/site Based on the official image `php:5.6-apache`, it installs missing packages to the system, adds mod-rewrite and mod-ssl to Apache, plus a number of PHP modules needed by Processwire (core or modules): mysqli, pdo_mysql, iconv, mcrypt, zip, and gd. Then it copies the site files to the location expected by the Apache server. Finally it declares a Docker volume `/var/www/html/site` (i.e. the site files and assets), so that it can be shared with other containers. 3. Set the msmtp configuration We need to configure a sendmail utility, so that we can send emails from php, for example when a user registers on the website. The simplest way to do it is to rely on an external smtp server to do the actual sending. That's why we use msmtp. - define the desired smtp account in `config/msmtprc` account celedev-webmaster tls on tls_certcheck off auth on host smtp.celedev.com port 587 user webmaster@celedev.com from webmaster@celedev.com password thepasswordofwebmasteratceledevdotcom - in `config/php.ini`, configure the sendmail command so it uses msmtp: sendmail_path = /usr/bin/msmtp -C /usr/local/etc/php/msmtprc --logfile /var/log/msmtp.log -a celedev-webmaster -t 4. Build the Docker image docker build -t php-5.6-pw-celedev . 5. Create a Data-only container for the site files docker run --name celedev-data php-5.6-pw-celedev echo "Celedev site data-only container" 6. Run the web server container docker run --name celedev-site -p 8088:80 --link database:mysql --volumes-from celedev-data -d php-5.6-pw-celedev Note that this container is linked to our database and shares the 'celedev-data' volume created previously During development, it can be convenient to keep an access to the host file system from the container. For this, we can add a shared volume to the previous command: docker run --name celedev-site -p 8088:80 --link database:mysql -v /Users/jean-luc/web/test-docker:/hostdir --volumes-from celedev-data -d php-5.6-pw-celedev Our ProcessWire website is now up and running and we can test it in our browser at http://hostaddress:8088. Great! What we now have in Docker bash-3.2$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE php-5.6-pw-celedev latest 2aaeb241c2e2 3 hours ago 1.149 GB nazarpc/phpmyadmin latest e25cd4fd48b3 8 days ago 521 MB mariadb latest dd208bafcc33 2 weeks ago 302.2 MB debian latest 9a61b6b1315e 5 weeks ago 125.2 MB bash-3.2$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 68cc5d976f0d php-5.6-pw-celedev "apache2-foreground" 20 hours ago Up 20 hours 443/tcp, 0.0.0.0:8088->80/tcp celedev-site 0729fe6d6752 php-5.6-pw-celedev "echo 'Celedev site d" 20 hours ago Exited (0) 20 hours ago celedev-data e3e9e3a4715c mariadb "/docker-entrypoint.s" 3 days ago Up 3 days 3306/tcp database Saving the site data We can create an archive of the site files by running a tar command in a dedicated container: bash-3.2$ docker run --rm -it --volumes-from celedev-data -v /Users/jean-luc/web/test-docker:/hostdir debian /bin/bash root@2973c5af3eaf:/# cd /var/www/html/ root@2973c5af3eaf:/var/www/html# tar cvf /hostdir/backup.tar site root@2973c5af3eaf:exit bash-3.2$ Tagging and archiving the Docker image We can also add a tag to the docker image that we have created in step 4 (recommended): bash-3.2$ docker tag 2aaeb241c2e2 php-5.6-pw-celedev:0.11 bash-3.2$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE php-5.6-pw-celedev latest 2aaeb241c2e2 3 hours ago 1.149 GB php-5.6-pw-celedev 0.11 2aaeb241c2e2 3 hours ago 1.149 GB nazarpc/phpmyadmin latest e25cd4fd48b3 8 days ago 521 MB mariadb latest dd208bafcc33 2 weeks ago 302.2 MB And we can archive this image locally if we dont want to push it now to the Docker Hub: bash-3.2$ docker save php-5.6-pw-celedev:0.11 | gzip > php-5.6-pw-celedev-0.11.tar.gz And that's it! You now have a portable image of your ProcessWire website that you can run directly on any docker-compatible system.1 point
-
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 }1 point
-
Thanks everyone! @rick Yeah, as I said I'm planning to release the first alpha version in a couple of weeks, your feedback will be very welcome.1 point
-
Welcome to the board mauricius. This is a great module! Thanks for your work. Can't wait to try it out. Do you plan an alpha release soon? [edit] Fast trigger finger1 point
-
Welcome @mauricius. This looks really awesome! PS: Best way to get early feedback is to publish a alpha- or beta-state github repo and post the link here. EDIT: PPS: yuhu, I saw & liked it first!1 point
-
You don't need the brackets or the last ?>. What's $page->children doing there? Just use ... echo $content; ... and you're fine. Complete solution: <?php $content = ""; // Set variable $content .= "<div class='pollino_poll'>"; // .= means append this string/text too $content .= "<div class='inner'>"; $content .= "<h3>$page->title</h3>"; $content .= $modules->Pollino->renderPoll($page); $content .= "</div>"; $content .= "</div>"; echo $content; // Output variable1 point
-
For some cases, it's a matter of preference. What's also cool about the inheritance route, is that you can use type hinting in your methods and functions. It makes the code more readable and also protects from errors. Also there is always some overhead (even though very small) when you are executing hooked methods. As you already noticed, you can use conditional hooks. And you can of course check the template of the Page in question inside the hook as well. Anyway, I would go with inheritance in your case. First and foremost because you don't need any autoloading modules, and you never have to wonder 'where the heck did I put that hook'. In my opinion it makes your application more manageable.1 point
-
@kongondo - {title} is working fine for me. I am assuming its pulling the title field with this.1 point
-
@Mike, your module is insanely amazing! Love it, I just switched to using your module for redirects. You saved me hours!! of inputting a bunch of redirects. I used the wild card. I set it up like this: blog/{year:num}/{month:num}/{day:num}/{title:segment}/ going to domain/blog/posts/{title}/ and its working flawlessly!!!1 point
-
Often those accessable url's are used for the pages only showing a specific category, but you can surely prevent that. One way would be using only templates without a corresponding template.php file. If there's no file, then there's nothing to render, which results in the default 404 error. Another way would be using the right selector to get the categories $pages->find("parent.id=[path=/categories, include=unpublished]"). This does get you all children of the page found by the selector within the square brackets (subselector). Keep in mind, that urls are always lowercase.1 point
-
Hi Guys, A new launch from us. Ensoul.co.uk - Interior Design, Architecture & Project Management, London. Background Based in London, Ensoul are Interior Architects specialising in high-end / luxury interiors, basement conversions, extensions, and residential renovations etc. We based the site on ProcessWire because it's agile, scalable and a pleasure to work with. Given that the Ensoul team will shortly be updating the site and blog in-house we needed a CMS that would also be intuitive for them to use. Overall the nature of the site is very visual and relies heavily on photography. It was essential the CMS had solid image management built in and this was another factor in choosing to run it on ProcessWire. More on that shortly. The plan This is Phase 1 (design and launch) of a multi phase project. Phase 2 consists of optimisation, refinement and a comprehensive SEO project. In particular we'll be redesigning the homepage, building a blog and looking to speed up page loads. With ProCache due to be installed very shortly, we plan to dramatically increase the site speed, minify a lot of the JS and gain points on Googles mobile speed test tool. Image Management I just wanted to highlight some of the nice image management features which ProcessWire brought to the table. 1. Background images Most of the pages have a large background image and we wanted the freedom to swap and change these on a page by page basis and test a lot of different photos. Given 80% of the page and background image is covered by content, not every image was going to work. We solved this simply by creating an image filed called Background Image into which we (or client) can drag and drop a photo of their choice. Any background photos are integrated into the jQuery Backstretch plugin In the case of the homepage where three background images are used, PW and Backstretch will create a slideshow instead. <?php // if Background_Image field contains more than 1 photo, echo the images in a slideshow // Mainly for Homepage if($page->Background_Image->count > 1 ) { $bgimage = $page->Background_Image; echo '<script>$.backstretch(["'; echo $bgimage->implode('", "', "url"); // results in url", "url", "url echo '"], {duration: 5000, fade: 1000});</script>'; } else // otherwise echo a single image on its own // Mainly for all other pages if($page->Background_Image->count == 1 ) { $bgimage = $page->Background_Image; foreach ($bgimage as $image) { echo" <script> $.backstretch('$image->url'); </script> "; } } ?> 2. Portfolio The Portfolio page is image heavy and features a masonry grid of photos which are then filtered by project type. On the front end, I was able to restrict each thumbnail and pop-up image to the size of my choice without having to crop each individual photo. To achieve this, I used a $thumb and $large variable and PW automagically handled the cropping. foreach($page->Images as $image) { $large = $image->width(800); $thumb = $image->size(340); echo ".... Creating the filters which toggle the display of rooms by type was surprisingly easy with ProcessWire. I used the image tag field which I hadn't really used before and quickly allowed me to tag a photo as a kitchen, bedroom or basement etc. It really was an eye opener into the power of PW: <div class="portfolioFilter"> <strong>View:</strong> <a href="#" data-filter="*" class="current">All</a> <a href="#" data-filter=".Kitchen">Kitchen</a> <a href="#" data-filter=".Bedroom">Bedroom</a> <a href="#" data-filter=".Bathroom">Bathroom</a> <a href="#" data-filter=".Sitting-Room">Sitting Room</a> <a href="#" data-filter=".Gym">Gym</a> <a href="#" data-filter=".Basement">Basement</a> <a href="#" data-filter=".Home-Office">Home Office</a> <a href="#" data-filter=".Kids">Kids</a> <a href="#" data-filter=".Garden">Garden</a> </div> <div class="portfolioContainer"> <?php foreach($page->Images as $image) { $large = $image->width(800); $thumb = $image->size(340); echo " <a class='fancybox-portfolio port-item {$image->tags}' href='$image->url' rel='gallery1'> <img src='$thumb->url' alt='$thumb->description' class='portfolio-thumb'> </a>"; } ?> </div> 3. Coverage Thumbs The client is receiving regular coverage in leading interior design magazines and at the end of the project I required a way to differentiate between Features and Opinion pieces. Again, PW made this very easy for me. I knew I could easily create a field called Coverage Type and select the type of coverage a publication should belong to. Traditionally I would have relied on the Page field to achieve this but I didn't need the initial more involved setup which that would require. Instead I opted for the new, simpler Options field instead. Featured Modules RenoTheme CoreConfig Upgrade Markup Simple Navigation CroppableImage FormBuilder ProCache (shortly) SEO Page Path History Redirects SiteMap XML ListerPro WireMail SMTP Conclusion That's pretty much it. I know some of the techniques here won't set the PW world on fire and probably are pretty basic but hopefully seeing the screengrabs and examples will help other beginners understand PW a little better. Thanks as always to the PW community who helped build this with their advice and answers along the way.1 point
-
@valan Looking through your code, I think that the problem could be this line: https://github.com/valieand/GoogleCidCatcher/blob/master/GoogleCidCatcher.module#L195 If your array is empty, you get a strange selector string. Also you are using array_filter without actually filtering anything in the array, not sure how PHP behaves. Normally you'd need to pass a closure as second argument, see: http://php.net/manual/en/function.array-filter.php Edit: Ok just read the docs, if you omit the closure as second argument when using array_filter, all FALSE entries are removed.1 point
-
What if you add this to your config.php? $config->sessionFingerprint = false;1 point
-
Hi Horst, I've used weighten in a newsletter tool for company logo's and it working great. Thanks again for implementing it !1 point
-
Here's how it worked for me in CKEditor (in case you persist on this route - but I would go for Hanna Code as Adrian suggested. As usual, the "culprit" is our friend HTML Purifier (read from here up to and including Ryan's comment here about its pros and cons before deciding whether to implement #5 below!) For iframes, the Extra allowed content seems to have no effect - btw, the correct syntax here is for example, div(*) not div[*] Add 'Iframe' (note the spelling) to your CKEditor Toolbar Leave ACF on No need to switch the field's "Content Type" from "Markup/HTML" to "Unknown" Turn HTML Purifier off (gasp! ) Enjoy your embedded video1 point