Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/05/2013 in all areas

  1. Hi all, I'm a big fan of the Sublime Text 2 text editor and of course of huge fan of ProcessWire, so I went ahead and created a library of PW snippets to be used with the ST2 Snippet system. I followed the PW cheat sheet, and created Advanced and Basic versions. The Advanced version contains only those seen in the advanced mode of the cheat sheet, so if you want the full set, you'll want to get both Basic and Advanced. They are on GitHub here: https://github.com/evanmcd/SublimeProcessWireSnippetsBasic https://github.com/evanmcd/SublimeProcessWireSnippetsAdvanced I've just submitted the Advanced set for inclusion into Package Manager, so hopefully that will be added soon. See the README for more info. Any feedback welcomed
    2 points
  2. "Selection: Male or Email"? That sounds... a bit strange.
    2 points
  3. You'll find what you ask here http://wiki.processwire.com/index.php/Module_Creation
    2 points
  4. Since you guys asked for it, I'll take a stab at a case study on the development process. Most of the development was done in about a week and a half. I started with the basic profile, but it ended up being something somewhat similar to the Blog profile in terms of how it's structured. Below I'll cover some details on the biggest parts of the project, which included data conversion, the template structure, the front-end development and anything else I can think of. Data Conversion from WordPress to ProcessWire One of the larger parts of the project was converting all of the data over from WordPress to ProcessWire. I wrote a conversion script so that we could re-import as many times as needed since new stories get added to cmscritic.com almost daily. In order to get the data out of WordPress, I queried the WordPress database directly (my local copy of it anyway) to extract what we needed from the tables wp_posts for the blog posts and pages, and then wp_terms, wp_term_relationships, and wp_term_taxonomy for the topics and tags. WordPress stores its TinyMCE text in a state that is something in between text and HTML, with the most obvious thing being that there are no <p> tags present in the wp_posts database. Rather than trying to figure out the full methodology behind that, I just included WP's wp-formatting.php file and ran the wpautop() function on the body text before inserting into ProcessWire. I know a lot of people have bad things to say about WordPress's architecture, but I must admit that the fact that I can just include a single file from WordPress's core without worrying about any other dependencies was a nice situation, at least in this case. In order to keep track of the WordPress pages imported into ProcessWire through repeat imports, I kept a "wpid" field in ProcessWire. That just held the WordPress post ID from the wp_posts table. That way, when importing, I could very easily tell if we needed to create a new page or modify an existing one. Another factor that had to be considered during import was that the site used a lot of "Hana code", which looked like [hana-code-insert name="something" /]. I solved this by making our own version of the Hanna code module, which was posted earlier this week. Here's an abbreviated look at how to import posts from WordPress to ProcessWire: $wpdb = new PDO("mysql:dbname=wp_cmscritic;host=localhost", "root", "root", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'")); $posts = wire('pages')->get('/posts/'); $sql = " SELECT * FROM wp_posts WHERE post_type='post' AND post_status='publish' ORDER BY post_date "; $query = $wpdb->prepare($sql); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { $post = $posts->child("wpid=$row[ID]"); // do we already have this post? if(!$post->id) { // create a new post $post = new Page(); $post->template = 'post'; $post->parent = $posts; echo "Creating new post...\n"; } $post->of(false); $post->name = wire('sanitizer')->pageName($row['post_name']); $post->title = $row['post_title']; $post->date = $row['post_date']; $post->summary = $row['post_excerpt']; $post->wpid = $row['ID']; // assign the bodycopy after adding <p> tags // the wpautop() function is from WordPress /wp-includes/wp-formatting.php $post->body = wpautop($row['post_content']); $post->save(); echo "Saved post: $post->path\n"; } What I've left out here is the importing of images, topics, tags, and setting the correct authors for each post. If anyone is interested, I'll be happy to go more in depth on that, but didn't want to overwhelm this message with code. Template File Structure This site makes use of the $config->prependTemplateFile to automatically include the file _init.php before rendering a template file, and $config->appendTemplateFile to automatically include the file _main.php after. So the /site/config.php has this: $config->prependTemplateFile = '_init.php'; $config->appendTemplateFile = '_main.php'; You may recognize this as being the same setup from the Skyscrapers profile. The _init.php includes files containing functions we want to be available to all of our templates, and set default values for the regions we populate: /site/templates/_init.php /** * Include function and hook definition files * */ require_once("./includes/render.php"); require_once("./includes/hooks.php"); /** * Initialize variables populated by templates that get output in _main.php * */ $browserTitle = $page->get('browser_title|title'); $body = "<h1>" . $page->get('headline|title') . "</h1>" . $page->body; $side = ''; $renderMain = true; // whether to include the _main.php file The includes/render.php file that is included above includes several functions for generating markup of navigation and post summaries, or any other shared markup generation functions. Examples are renderPost(), renderNav(), renderTags(). This is similar to the blog.inc file from the Blog profile except that I'm letting these functions generate and return their own markup rather than splitting them into separate view files. I personally find this easier to maintain even if it's not as MVC. The includes/hooks.php sets up any hooks I want to be present for all of my templates. I could have also done this with an autoload module, but found this to just be a little simpler since my hooks were only needed on the front-end. The main hook of interest is one that makes all posts look like they live off the root "/" level rather than "/posts/" (where they actually live). This was in order to keep consistency with the URLs as they were in WordPress, so that the new site would have all the same URL as the old site, without the need for 301 redirects. /site/templates/includes/hooks.php /** * This hook modifies the default behavior of the Page::path function (and thereby Page::url) * * The primary purpose is to redefine blog posts to be accessed at a URL off the root level * rather than under /posts/ (where they actually live). * */ wire()->addHookBefore('Page::path', function($event) { $page = $event->object; if($page->template == 'post') { // ensure that pages with template 'post' live off the root rather than '/posts/' $event->replace = true; $event->return = "/$page->name/"; } }); Our /site/templates/_main.php contains the entire markup for the overall template used site wide, from <html> to </html>. It outputs those variables we defined in _init.php in the right places. For example, $body gets output in the <div id='bodycopy'>, $side gets output in the right <aside>, and $browserTitle gets output in the <title> tag. /site/templates/_main.php <?php if($renderMain): ?> <html> <head> <title><?=$browserTitle?></title> </head> <body> <div id='masthead'> // ... </div> <div id='content'> <div id='bodycopy'><?=$body?></div> <aside id='sidebar'><?=$side?></aside> </div> <footer> // ... </footer> </body> </html> <?php endif; ?> We use the rest of the site's template files to simply populate those $body, $side and $browserTitle variables with the contents of the page. As an example, this is an abbreviated version of the /site/templates/post.php template: /site/templates/post.php // functions from /site/templates/includes/render.php $meta = renderMeta($page); $tags = renderTags($page); $authorBox = renderAuthor($page->createdUser); $comments = renderComments($page); $body = " <article class='post post-full'> <header> <h1>$page->title</h1> $meta </header> $page->body $tags $authorBox $comments </article> "; if(count($page->related)) { $side = "<h4>Related Stories</h4>" . renderNav($page->related); } What might also be of interest is the homepage template, as it handles the other part of routing of post URLs since they are living off the root rather than in /posts/. That means the homepage is what is triggering the render of each post: /site/templates/home.php if(strlen($input->urlSegment2)) { // we only accept 1 URL segment here, so 404 if there are any more throw new Wire404Exception(); } else if(strlen($input->urlSegment1)) { // render the blog post named in urlSegment1 $name = $sanitizer->pageName($input->urlSegment1); $post = $pages->get("/posts/")->child("name=$name"); if($post->id) echo $post->render(); else throw new Wire404Exception(); // tell _main.php not to include itself after this $renderMain = false; } else { // regular homepage output $limit = 7; // number of posts to render per page $posts = $pages->find("parent=/posts/, limit=$limit, sort=-date"); $body = renderPosts($posts); } The rest of the site's template files were handled in the same way. Though most were a little simpler than this. Several were simply blank, since the default values populated in _init.php were all that some needed. Front-end development using Foundation 4 The front-end was developed with the Foundation 4 CSS framework. I started with the Foundation blog template and then tweaked the markup and css till I had something that I thought was workable. Then Mike and I sent the _main.php template file back and forth a few times, tweaking and changing it further. There was no formal design process here. It was kind of a photoshop tennis (but in markup and CSS) where we collaborated on it equally, but all under Mike's direction. After a day or two of collaboration, I think we both felt like we had something that was very good for the reader, even if it didn't originate from a design in Photoshop or some other tool like that. I think it helps a lot that Foundation provides a great starting point and lends itself well to fine tuning it the way you want it. I also felt that the mobile-first methodology worked particularly well here. Comments System using Disqus We converted the comments system over to Disqus while the site was still running WordPress. This was done for a few reasons: Disqus comments provide one of the best experiences for the user, in my opinion. They also are platform agnostic, in that we could convert the whole site from WP to PW and not have to change a thing about the comments… no data conversion or importing necessary. Lastly, ProcessWire's built-in comments system is not quite as powerful as WordPress's yet, so I wanted cmscritic.com to get an upgrade in that area rather than anything else, and Disqus is definitely an upgrade from WP's comments. In order to ensure that Disqus could recognize the relations of comment threads to posts, we again made use of that $page->wpid variable that keeps the original WordPress ID, and also relates to the ID used by the Disqus comments. This is only for posts that originated in WordPress, as new posts use a ProcessWire-specific ID.
    1 point
  5. Hi Folks, today we will learn how to set up a simple jquery plugin called calendario and fill events trough our admin backend. || ATTENTION || Modern Browser needed First of all, we need the jquery plugin. Grab your copy here: http://tympanus.net/...alendar-plugin/ Now create a new template file, lets call the file calendar.php In the next step we have to include all the needed files from the .zip package. You need the following .css files: calendar.css custom_2.css demo.css Just include them in the <head> </head> of your template file. Feel free to merge them together, so you could save some http connects. Now we need to include the needed javascript. Make sure you have included the latest jQuery library. Include the jquery.calendario.js and the modernizr.custom.63321.js right into the bottom of your template file. Save the calendar.php Now we will set up Processwire where the magic wil happen. We just need one new template. Create a new template called calendar. Assign the field headline to our template. Allow children to just use this template. Hit the save button. Now create a new Page as child of home and call it Calendar. Assign our calendar template to this page. Almost ready. Now we have to do some little scripting in our template file calendar.php Add this html markup to our calendar.php <div class="custom-calendar-wrap"> <div id="custom-inner" class="custom-inner"> <div class="custom-header clearfix"> <nav> <span id="custom-prev" class="custom-prev"></span> <span id="custom-next" class="custom-next"></span> </nav> <h2 id="custom-month" class="custom-month"></h2> <h3 id="custom-year" class="custom-year"></h3> </div> <div id="calendar" class="fc-calendar-container"></div> </div> </div> Now we have to call the javascript function, to get the calendar running. Just put this snippet right under the included jquery.calendario.js <script type="text/javascript" $(function() { var transEndEventNames = { 'WebkitTransition' : 'webkitTransitionend', 'MozTransition' : 'transitionend', 'OTransition' : 'oTransitionend', 'msTransition' : 'MSTransitionend', 'transition' : 'transitionend' }, transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ], $wrapper = $( '#custom-inner' ), $calendar = $( '#calendar' ), cal = $calendar.calendario( { onDayClick : function( $el, $contentEl, dateProperties ) { if( $contentEl.length > 0 ) { showEvents( $contentEl, dateProperties ); } }, caldata : { <?= getEvents(); ?> // this is our function to grab our events }, displayWeekAbbr : false } ), $month = $( '#custom-month' ).html( cal.getMonthName() ), $year = $( '#custom-year' ).html( cal.getYear() ); $( '#custom-next' ).on( 'click', function() { cal.gotoNextMonth( updateMonthYear ); } ); $( '#custom-today' ).on( 'click', function() { cal.gotoNow( updateMonthYear ); } ); $( '#custom-prev' ).on( 'click', function() { cal.gotoPreviousMonth( updateMonthYear ); } ); function updateMonthYear() { $month.html( cal.getMonthName() ); $year.html( cal.getYear() ); } // just an example.. function showEvents( $contentEl, dateProperties ) { hideEvents(); var $events = $( '<div id="custom-content-reveal" class="custom-content-reveal"><h4>Termine am ' + dateProperties.day + '. ' + dateProperties.monthname + ' ' + dateProperties.year + '</h4></div>' ), $close = $( '<span class="custom-content-close"></span>' ).on( 'click', hideEvents ); $events.append( $contentEl.html() , $close ).insertAfter( $wrapper ); setTimeout( function() { $events.css( 'top', '0%' ); }, 25 ); } function hideEvents() { var $events = $( '#custom-content-reveal' ); if( $events.length > 0 ) { $events.css( 'top', '100%' ); Modernizr.csstransitions ? $events.on( transEndEventName, function() { $( this ).remove(); } ) : $events.remove(); } } }); </script> We are almost finished, but we are missing some very essential, have a look to our javascript. We are calling a function named getEvents() This function will grab our events and fire it right to our calendar. So here is the code: function getEvents() { $events = wire('pages')->get("/calendar/")->children(); foreach ($events as $event) { echo "'$event->title' : '<span>$event->headline</span> ',"; } } Put this snippet above the javascript includes. We will now create our first entry. Go back to the PW admin backend and create a Child of Calendar. Title and name need the Date on which the event has to be displayed. You have to form a date in this format: mm-dd-yyyy e.g. 12-27-2012. The headline field is our Event description. Hit the save button, go to your site and enjoy your event calendar. With a little coding you could extend the calendar to let it look like mine attached as screenshot. Hope this was useful to somebody. Cheerio.
    1 point
  6. Hi all, I've finally managed to set up my website where I intend to post ProcessWire tutorials. The site (lessons) is very much WIP. I have tried to make the site as responsive as possible. I have only tested in Chrome and FF. I'd rather write more lessons than test in IE to be honest so I won't pursue that... I will try to post regularly but can't make any promises as to the frequency . I intend to randomly post some pre-planned lessons. I will update this forum post everytime I post something new. If you have questions, pointers, etc about any lesson, or a request for a specific lesson, please post them here. This way, other forum members can assist in answering the questions . Thanks. /k ==================================================================== Edit: 28 August 2014 - Fist Tutorial is up (OK, it's Blog Module documentation ) Creating a Blog in ProcessWire (Blog Module how to) - 28 August 2014 [99% done] Next: 'All you ever wanted to know about ProcessWire Modules [and other cool things]' - COMING very SOON
    1 point
  7. More and more, processwire has become my personal haven... I do almost no commercial work with it (I work as a dev, and for payed side-projects I suffer the dread of joomla droppings ) Made this "thing": - http://www.lisboncorrespondent.com/ This is a blog (of sorts) for my father, with make-pretend postcards sent from Portugal. It is essentially a way for me to experiment with and learn a few techs/tools: css 3d transforms (and respective headaches, cross-browser issues, etc) The wonderful angularJS framework Yeoman (build system for js apps, with grunt + bower) Processwire, of course Processwire is amazing for every crazy thing I may ever think up, and using it as a simple RESTy service provider is incredibly simple. Gotchas: This will most likely be a perma-beta site - it is for trying stuff No history back/forward or direct urls - angularJS makes it easy, but it wasn't really my concern. Will have to happen someday, though No SEO whatsoever - I'm perfectly aware that a "blog" in a one page app is a no-no, but again, just toying around Tested with Chrome, Firefox and IE 10, OSX and Win - further compatibility (and mobile) to come Hope you enjoy. And thank you, Ryan, for the wonderful gift of processwire
    1 point
  8. I've posted an update to Hanna Code to address some of the things brought up earlier: It now comes with a proper code editor (Ace Editor). You can configure the theme and editor height in the ProcessHannaCode module settings. There is now a "Save & Test" option. When you click that, it will save then attempt to run the Hanna code. This is primarily useful for determining if you have any PHP parse errors or the like. The default behavior of "Save" is now to continue editing, rather than going back to the list of Hanna codes. There is now a separate "Save & Exit" button to do that. The interface now uses tabs.
    1 point
  9. Hi, Thomas and welcome to the forums! From some of the details in your question, it looks like you have some experience in these matters, so I won't go through the obvious suggestions. The problem does indeed look like an .htaccess problem. There is some info about getting PW working on 1&1 starting here http://processwire.com/talk/topic/264-editing-htaccess-%E2%80%93-ok-or-not/#entry1788 I can't vouch for it's accuracy but it looks like it addresses similar problems to those you are having. Take a look, and if it doesn't help, come back here and I'm sure we can get you working.
    1 point
  10. Super cool ideas, thanks a lot! Point #3 sounds really good. The more I learn about ProcessWire and use it, the more I love it.
    1 point
  11. I can think of different ways to deal with this one. Printout: As someone suggested in the forums (Maybe Renobird?), they print out a list of all the fields on their site and what the fields are for. Admin page: Maybe create a hidden page, under Admin, with a list of all the fields and what they represent for each company? Custom Admin page: Create a custom admin page using Diogo's Admin Custom Page module that renders only for superuser showing you the list of fields and what they represent for each company. Maybe this is best because you can view it as read only and can get as creative as you want with the output Just thinking out loud here...
    1 point
  12. wow! works! weird though coz admin template has "allow page numbers" checked and not urlsegments. and yes, I had the "process" field on the custom admin template and it was working just fine - as long as you set alternate template to "admin" - except for the urlsegments thing. anyway, thanks for pointing me in the right direction
    1 point
  13. You can do this in ProcessModules. If no URL segment is given, ProcessWire executes the execute() method of your class. If you visit the module with an urlSegment, Pw executes the executeNameofurlsegment() method. Example: I used this in my Google Analytics module to load the statistics for the different sections with ajax: https://github.com/wanze/ProcessGoogleAnalytics/blob/master/ProcessGoogleAnalytics.module#L357 What does the code of your module look like? Do you extend Process?
    1 point
  14. Adrian, My code above only works for pages that have already been saved to the database and therefore have a page id. When used with the title tag, however, this is a problem, as the value for this field must be set before the page is saved. As it turns out you already anticipated this use case by calculating the unique value based on the id of the last page saved to the database: http://processwire.com/talk/topic/4201-how-to-automatically-set-the-value-of-a-field/#entry41172 I marked your answer as the best answer, so that others will find your solution faster than I did. Cheers, Stefan
    1 point
  15. Hi Rjay, thanks for the prompt response! I have that folder to 755 What permissions do you have for yours? Do you have any .htaccess settings for both main sitedomain.com and siteotherdomain.com on the servers LAMP public_html or www folder? UPDATE: Its working now I had some .htaccess settings on the public_html folder, I forgot to remove for the multisite to work. Thanks for all your help Rjay.
    1 point
  16. If you hook before render, there's no $event->return (yet). So you can't replace anything, only if you echo out your stuff and exit() it will work. This has been like this ever since, and I know because I played with it, but never actually needed it or seen any use for it.
    1 point
  17. Stefan, I believe the only reason why your code wasn't working is because you were using $this->addHookAfter. You'll notice that the code I put together uses $this->addHookBefore. You need to populate the value before rendering the field. As for the automatic filling error. Ryan has autocomplete="off" set for the form when editing an existing page. I have also seen this browser produced warning - it is not actually an error. Did you try the module I put together? You can easily change the fields that are being dynamically set to whatever you want.
    1 point
  18. Please don't pay any attention to systemVersion. I was just trying to explain what it was for those interested, but it's not something anyone but core devs need to think about. The dev branch is not an official release and I want to be careful about anything that might present it that way. People don't even need to know about the dev branch unless they are interested in helping to test or develop ProcessWire, or (in this case) take advantage of the multi-language updates before they appear in PW 2.4. It's a branch that gets updated a few times a week, sometimes even daily or more. For a dev branch like this, the commit ID is the version, and the commit log is the README. Everything on dev is basically "being prepared" for an official release, so you wouldn't typically have separate README files for master vs. dev, etc., because dev is not a release, it's a branch working to eventually become a release. It's best to follow the commit log of the dev branch to see what's happening. It's also best to use the dev branch with Git (git checkout dev), and not by downloading a ZIP file. Typing "git status" will tell you what branch you are on (master or dev), and "git pull" will pull in the latest version instantly. I understand that Git can be confusing and a whole lot to figure out (I'm still learning it myself), but we are getting into the nature of how Git and software development work. The audience here is intended to be developers and testers, where Git is the standard. It's not supposed to be neatly packaged, versioned and ready for the consumer, and will always take more time investment on the part of anyone using it. We want users to have some experience with Git when using the dev branch because we are asking them to help test, report, and potentially fix issues through the GitHub system. I think part of the confusion here is just that we are getting very close to a 2.4 official version release and the dev branch is quite stable. So the distinction between official release and dev is probably more blurry than usual. Without thinking much about it, I've been casually telling people to use dev when it seems to make sense. But that will change as we hopefully release version 2.4 soon.
    1 point
  19. What you see on modules.processwire.com is part of a new Fieldtype module I've been developing on and off to support "like" buttons or star ratings by users. The implementation you see on the modules site enables anyone to anonymously "recommend" (like) a module, though the module itself does support limiting access to roles. When it comes to anonymous voting, the system prevents duplicates by both cookies and IP addresses, which isn't foolproof, but it's the best you can do short of having an authenticated user. It also requires Javascript and uses some cookie tricks, to keep the crawlers from voting. I put it up there a few days ago without mentioning it, and am surprised already at how much "recommending" has been going on, good to see. I'm also glad to hear there is interest in a module like this. I will keep working on it! It will also come with a Process module (under Setup) that lets you browse the liked pages in your admin For the star ratings part, I feel like this really is best kept to authenticated users (since one can also down-vote), so am looking into ways to limiting rating to those with PW user accounts and/or Twitter/Facebook/Linkedin accounts. I might ultimately just make the star ratings one a separate module, but still dwelling on it. Good idea, I will add this to the core.
    1 point
  20. TinyMCE can be a bear sometimes. I don't know how to accomplish what you are trying to do, and most likely this is a question more for the TinyMCE forums than here. But the first thing I would try is to open the code editor, insert an , close the code editor, then open it again. Is the still there, or did TinyMCE get rid of it? This might point to whether you are dealing with a filter or not. Or, does the only disappear after saving the page?
    1 point
  21. In my experience, clients understand and accept very well when you tell them that you created some constrains on purpose. The important is that they look at their website and their friend's website and see why theirs looks much better.
    1 point
  22. I've never come across a client that didn't prefer a rich text editor to the alternatives. The reality is, they like RTEs because it's something they are already familiar with and it's easy for them to use. So I think a better goal is to give them what they want, but place limits upon it so that it can't produce a mess. Just because RTEs+clients can create a mess doesn't mean we have to let them do it. Both our TinyMCE and CKEditor rich text inputfields come very much restrained and prevent the client from creating a mess. CKEditor4 and it's ACF (advanced content filter) seem particularly adept at solving this problem. If you can convince a client to use an LML (Markdown, etc.) or some method of creating content in blocks, then that's fine. But once the next guy comes around showing them "look what you can do in my CMS–it's like using Word", you may be at a disadvantage. Other factors to consider: 1) content maintained by blocks may be significantly less portable through future CMS changes, web service/syndication feeds and such; 2) it may be more difficult to maintain site-wide consistency with the designer's original vision if a site's main content area is a mashup of content blocks. Personally, I would avoid trying to pursue a blocks strategy for most content editors, whether in a CMS that is built around the concept, or via trying to build everything around Hanna Codes. Instead, let the designer do their job and determine consistent and well thought placements for photo galleries, navigation, etc. I see Hanna Code as being better for the exceptions of needing something somewhere, and not something that editors should have to keep as part of their vocabulary.
    1 point
  23. Andrew, That's obviously MODX syntax. Before I answer your question, I have two things to say: 1. Please, if you have a question, post in either the General Support or the Getting Started or the API & Templates sections of these forums according the the relevance of the question.. This is the Tutorials Section of the Board where your posts/threads should be teaching something rather than asking questions, thanks. 2. Have you read this guide to PW for those familiar with MODX? If not, please do. It will answer questions such as above. As you'll see from that guide, apart from the name of a page, all other fields on a page are custom fields. There is no default title, keywords, description, etc fields. You will have to create those fields and add them to your template. Then, create a page and make it use that template. If you want your keywords to be unique to each page, then do it this way (illustrated below). If you want your keywords to be the same across the whole site, then you can create a page that will act as a settings page. For now, I'am not going to go into details about such a setup but will let you explore the system more. OK, so, 1. Create the following fields types a. Name: keywords; Type: text or text area (depending on how much space you want) b. Name: description; Type: text area Make sure to give the fields labels and a "description" if you want to. Your PW install should already come with the title field (if you installed the default PW profile) 2. Add the fields to your template. Order the fields in the template as you wish 3. Create a page and make it use the template in #2 4. You will see the keywords, description and title fields on that page. Enter your keywords and description in the fields and edit the page as you wish. Hit save. 5. In your template file <meta name="keywords" content="<?php echo $page->keywords;?>"/> <meta name="description" content="<?php echo $page->description;?>"/> <meta name="robots" content="All"/> <title><?php echo $page->title;?></title> You don't need the <base> tag in ProcessWire. You can get fancy and only echo out the keywords and description if they are actually present on your page. How to do that? That'll be your homework
    1 point
  24. Hi nfil, Don't know whether I've said welcome to PW or not. If not, welcome . Are you allowing multiple or single file uploads on that field? If single... if ($page->pdf_docs_insert){ $myfile = $page->pdf_docs_insert; echo "<a href='{$myfile->url}' target='_blank'>$myfile->description</a>"; } else { // ... } If multiple files, the field returns an array, hence you need to loop through it... if ($page->pdf_docs_insert){ $myfiles = $page->pdf_docs_insert; foreach ($myfiles as $myfile) { echo "<a href='{$myfile->url}' target='_blank'>$myfile->description</a>"; } } else { // ...please give me some files mate! } Check out the cheatsheet for more info
    1 point
  25. I'd like to add a bit to the great material that has already been posted... Journey From the "Big Three" to ProcessWire... It might seem that ProcessWire is "elitist" because it doesn't assume anything. But let me share my experiences with you, which have led me to the opposite conclusion. I came to ProcessWire from the world of Joomla (and Drupal and WordPress), where all manner of web development building blocks are set up and built ready for you to use, to make your life easier. In fact, you might say that in this way a system like Joomla is the most un-elitist system out there. It assumes you know nothing, and holds your hand through every part of building a web site. For a couple of years, this was good for me. Until one day, when I learned some JQuery and wanted to implement some new concepts, or when I read on Stack Overflow about some creative ways to make PHP do what I need, or wanted to create a unique layout for a client and needed to start from a blank slate, or wanted my user registrations to look unique, or wanted my articles to have 20 separate fields, or wanted a tagging system that looked and behaved in a particular way, or wanted to set up custom search functions for my site. Suddenly, everything about Joomla's un-elitist approach felt stifling. At every step, if I was not doing something the "Joomla way," it didn't work or was 10 extra steps to override something. When I posted about this to the Joomla leaders, I was essentially told, "You don't do it that way in Joomla." When I switched to ProcessWire, I realized that I was now free to implement any good coding ideas I discovered on my own, or discovered on Stack Overflow, or read about in various CSS, Javascript, and PHP realms. Core Assumptions... ProcessWire makes only two assumptions: first, that you have a good grasp of foundational building blocks of the web; second, that you explore the API. On the first point, the assumptions ProcessWire makes are generally the same basic assumptions that would be made if you were developing sites in "pure" PHP/HTML/CSS/Javascript. In other words, any knowledge you gain about these foundational building blocks can be immediately implemented in ProcessWire. On the second point, yes, there are system-specific API elements you need to understand. But they are designed to cleanly facilitate depth and creativity in those foundational building blocks. ProcessWire Trusts Your Intelligence and Capabilities... Put all this together and what do you have? Well, you have a situation where you can create anything you want, because you can get at the foundations of systems that exist on the web. For example, if you need a tagging system, you can learn what constitutes a tagging system. What are the core principles of tagging? Once you understand it, you can build it in ProcessWire. Not only that, but you can build it your way, with no assumptions, freely. If you come from a system like Joomla, Drupal, or WordPress, this means you may have to learn a few new ways to work. But those ways of working -- again -- go directly to the basic building blocks of the web. I know from experience that the un-elitist approach used by Joomla, Drupal, and WordPress seem to be nicer but actually turn out to be very harmful to your individual progress because they delay your exploration of these foundational building blocks. With ProcessWire, because it trusts you to use those foundational building blocks, the knowledge you gain using ProcessWire is applicable beyond ProcessWire and helps you no matter how you create web applications. Put another way, ProcessWire allows you to explore and build in the most un-elitist way possible. With that Said... After all this, there is of course some system-specific material to learn. There is the ProcessWire API, which is unique to ProcessWire. The system has been developed to get as close as possible to "pure" expression, and the syntax of ProcessWire's API calls have only what is needed to get at your data. But yes, there is API syntax to learn here, and the list of specific calls is pretty long. There are "best practices" for combining API elements. There are general goals that we all need for our web applications (galleries, tagging, user registrations, forms, etc) and somewhere there is a good combination of ProcessWire API calls to make them happen. What are those combinations? Well, usually there is more than one, because it depends on what you want to do in your application. The answer may not be pre-packaged, so you may have to hunt a bit. But I definitely agree that it would be great to have documentation of various methods (combinations of ProcessWire API calls and "pure" PHP/CSS/JS) to accomplish various goals. For that, we need what I would call "goal-oriented" documentation. I am proud to say that I am working on this right now. I have been working in silence. But discussions like this make me want to get it out there sooner. * * * I hope this helps a bit. Embrace the way ProcessWire allows you to work! Thanks, Matthew
    1 point
  26. Thanks for all the support, Ryan, Diogo, Soma and all the other forum members. I just finished my first pWire site. Although I still have to add the iOS icons and Soma´s great module for navigation markup doesn't seem to have the ability to limit the children <li> on my main menu, I will get that solved later. After a few weeks I'm very happy with process wire and every time I ask something here I feel a bit dumb. Process Wire simplicity to get things done is amazing! Thanks to kongondo too for the modx to pWire transition post: http://bit.ly/1dYgAnW You can check this simple and a bit text bloated pWire site here: http://artecassistencia.com
    1 point
  27. This hasn't been asked, but wanted to cover how the permissions and publish workflow work on the site. It has a very simple, though nice setup, where authors can submit new posts but can't edit already published posts, nor can they edit unpublished posts by other authors. It enables Mike to have full control over any content that gets published on the site, while still allowing easy submission and edits for the authors. Post workflow All of the authors have a role called "author" with page-edit permission. On the "post" template, the boxes for "edit" and "create" are checked for this "author" role. This site also makes use of the page-publish permission, which is an optional one in ProcessWire that you can add just by creating a new permission and naming it "page-publish". Once present, it modifies the behavior of the usual page-edit permission, so that one must also have page-publish in order to publish pages or edit already published pages. The "author" role does not have page-publish permission. As a result, authors on the site can submit posts but can't publish them. Nor can they edit already published posts. In this manner, Mike has final say on anything that gets posted to the site. Post ownership The default behavior in ProcessWire is that the Role settings control all access... meaning all users with role "author" would be able to do the same things, on the same pages. In this case, we don't want one author to be able to edit an unpublished/pending post created by another author. This was easily accomplished by adding a hook to /site/templates/admin.php: /** * Prevent users from being able to edit pages created by other users of the same role * * This basically enforces an 'owner' for pages * */ wire()->addHookAfter('Page::editable', function($event) { if(!$event->return) return; // already determined user has no access if(wire('user')->isSuperuser()) return; // superuser always allowed $page = $event->object; // if user that created the page is not the current user, don't give them access if($page->createdUser->id != wire('user')->id) $event->return = false; }); Planned workflow improvements Currently an author has to let Mike know "hey my article is ready to be published, can you take a look?". This is done by email, I'm assuming. An addition I'd like to make is to add a Page reference field called "publish_status" where the author can select from: DRAFT: This is a work in progress (default) PUBLISH: Ready for review and publishing CHANGE: Changes requested - see editor notes DELETE: Request deletion Beyond that, there is also an "editor_notes" text field that only appears in the admin. It's a place where Mike and the author can communicate, if necessary, about the publish status. This editor_notes field doesn't appear on the front-end of the site. All this can be done in ProcessWire just by creating a new field and adding these as selectable page references. That's easy enough, but I want to make it so that it notifies both Mike (the reviewer) and the author by email, every time there is a change in publish status or to the editor_notes. This will be done via another hook in the /site/templates/admin.php: wire()->addHookAfter('Page::saveReady', function($event) { // get the page about to be saved $page = $event->arguments(0); // if this isn't a post, don't continue if($page->template != 'post' || !$page->id) return; // if this post wasn't made by an "author" don't continue if(!$page->createdUser->hasRole('author')) return; $subject = ''; $message = ''; if($page->isChanged('publish_status') || $page->isChanged('editor_notes')) { // the publish status or editor notes have changed $subject = "CMSCritic post publish status"; $notes = $page->isChanged('editor_notes') ? "Notes: $page->editor_notes" : ""; $message = " Title: $page->title\n URL: $page->httpUrl\n Status: {$page->publish_status->title}\n $notes "; } else if($page->isChanged('status') && !$page->is(Page::statusUnpublished)) { // page was just published $subject = "CMSCritic post published"; $message = "The post $page->httpUrl has been published!"; } if($message) { $reviewer = wire('users')->get('mike'); $author = $page->createdUser; mail("$reviewer->email, $author->email", $subject, $message); $this->message("Email sent: $subject"); } }); Mike, if you are reading this, does this sound useful to you?
    1 point
  28. I agree, I think export/import methods like this on Fields and templates would be nice. There's a lot of considerations though, especially on import. Like whether individual fields already exist or not, whether those field definitions reference external things (like page IDs). That's not to say it isn't doable, but just that there is potential for it to get quite a bit more complex than it first appears. But I would like to implement some API level expor/import functions for this soon, to at least get things moving forward. I've already been working on similar export/import functions for Page objects (which you see in the latest dev branch, though they aren't yet active).
    1 point
  29. This case study relates to the topic here: http://processwire.c...ndpost__p__8988 about creating an archive of 'stories' about how PW has helped in relevant real life scenarios. Website: http://www.ray-dale.com RayDale Multimedia Ray Dale is a multimedia designer. His portfolio website was 2 years old as of March 2012 and in need of a refresh. He found that the content management for his website was more time consuming than he wanted and the website was generally slow in performance and complex to update. Ray needed: A website that could showcase his latest work with separate portfolio content types The ability to show lots of images and videos in each section Complex interlinking between each portfolio item - where each item would belong to a number of simultaneous categories To be able to publish a number of pages under various sections on the website To have a condensed navigation structure - not over-facing the user with navigation A blogging space that was easy to update To gain complete control over the HTML, CSS & JS markup and therefore the design of the website The ability to take more control over the admin experience - without using a host of plugins - so that the CMS could be used for clients to make their lives easier Speedy performance - even if a shared hosting platform were used Good site security The previous solutions Ray was previously using Drupal as a content management system. Drupal is a great system, it’s incredibly flexible, it can be made faster and using template overrides, almost complete control can be taken of the HTML and CSS output. However, the process to achieve any of this is time consuming and clunky from a web designer / front end developer perspective. Drupal was also going to require a number of plugins to be installed to achieve a lot of the required functionality. Ray tested migrating his website over to WordPress. WordPress is another fantastic blogging system with light CMS functionalities. WordPress is generally easier to use than Drupal and a lot of control over the HTML & CSS markup can be delivered - in a much easier manner than Drupal. However, WordPress is still light on CMS features in the admin system. This means that it is difficult without either using a lot of plugins or custom php development (using the WordPress API) to have custom content types and fields. The decision to use ProcessWire Having searched around for an alternative to Drupal and WordPress - revisiting other CMSs that Ray had also previously used - Ray eventually landed on ProcessWire having read about it on a forum. Right from watching the initial video produced by Ryan Cramer (the creator of ProcessWire) Ray was intrigued by the possibilities that ProcessWire seemed to offer - effectively solving all of the issues currently faced. To summarise ProcessWire offered: Custom content types in the admin Custom field types in the admin Good control over media uploads A simple to use admin system A neat and simple API for custom frontend / backend development A customisable admin experience The ability to have a custom admin url Complete control over HTML markup Good security with flood control A powerful and flexible templating system (that was also simple) Ray was extremely impressed by the features that ProcessWire offered, however, many CMSs look great until you actually start using them - where the unnecessary complexities, weak architecture and terrible, bloated functionality often start to appear. The functionality seemed so promising that a gamble was taken to build the Ray Dale Multimedia website - with very little time now available - to ProcessWire and test how it performed. Building the website Having built the original Ray Dale Multimedia website in Drupal, then converted to WordPress before deciding to gamble on ProcessWire - Ray now had very little time left to build his portfolio website. As a testament to the ease and speed of using ProcessWire - he was able (with a little help from articles in the forum) to rebuild the Ray Dale Multimedia website in two days of effective full time development. This included all of the content creation and learning the new system - with the inevitable (but surprisingly smooth) learning curve. Enabling complete control over output ProcessWire allowed Ray to write HTML and CSS without any of the interference you get from other CMS systems. So, Ray was able to use the following frameworks of his choosing: HTML5 boilerplate jQuery Modernizr Masonry A customised version of the 960 fluid grid system PrettyPhoto for lightbox images Less - to create minified CSS Though it must be said that literally anything can be used as ProcessWire makes no assumptions on the frontend - even on the Javascript framework. Quick and easy API One really pleasant surprise was the jQuery influenced API that ProcessWire offered. For example you can use php queries such as: $pages->find("selector"); $pages->get("selector, path or ID"); to find content in the system - you can even filter your queries by template type, fields attached to that item, etc. You can even use a range of selector operators. The API effectively works as a super powered and infinitely more flexible alternative to the WordPress loop. Cross referencing pages easily Complex cross-linking between portfolio items was needed so that capabilities, technologies and services could be linked to each item. It was easy to create a taxonomy system that worked the exact way required once the fundamental concept of how pages work in ProcessWire was understood. Building navigation that works Unlike a lot of CMSs that work effectively as ‘bucket systems’ - meaning that content is separate from any kind of structure or hierarchy by default in the system - whereas everything in ProcessWire is a page and arranged hierarchically. Whilst this may seem strange and restrictive to some used to the aforementioned ‘bucket systems’ - it works incredibly well and enables you to build navigational structures that are easy to plot a current location in. It is also something easy enough to break away from if you want a more ‘bucket’ type system. For example, in Drupal and WordPress it can be very difficult to highlight the navigation on a website if you are using custom content types. Try using custom post types in WordPress and keeping your navigation tracking which page the user has landed on - it’s extremely difficult without a fair bit of custom development (this is true as of the time of writing - WordPress 3.3.1). Because ProcessWire uses a structure and hierarchy by default - this structure makes building navigation that can track the current page very simple. Easy / flexible admin system The admin system in ProcessWire was easy and fluid to use, logical and stable. The admin system can also be overridden with templates (there are already some great community contributed templates). Modules used Whilst ProcessWire has a number of contributed modules from a thriving and helpful community - absolutely no additional modules were needed. All functionality on the website was achieved from a vanilla version of ProcessWire. Performance Another area of importance was the performance of ProcessWire. Again, Ray found this aspect to be well covered with built in caching capabilities that were thoughtfully included ‘out of the box’. The caching was simple to enable on templates and fields. The memory footprint of the Ray Dale Multimedia website was a third of that of Drupal on the same website without using addon caching plugins. Challenges The only real challenge faced was understanding that ‘pages are everything’ in ProcessWire. You build categories, taxonomy, articles, blog systems with the ‘page’ (and any fields it contains) being the basic building block for all of this. ‘Pages’ in ProcessWire can be attached to templates and injected with fields to enable the creation of literally anything conceivable. However, understanding this concept takes a little work for people used to other CMSs such as Drupal, WordPress and Joomla. However, in context - and compared to other systems - this learning curve is still fairly easy. There are so many other time savers that this learning curve becomes negligible. The other area that Ray had to understand about ProcessWire was that there aren’t any template system paradigms that exist in Drupal and WordPress. Other systems have parent and child templating systems with default parent templates that can be leveraged, however, because ProcessWire makes no assumptions on how you are going to build a project (being a true framework) you currently need to create your own template files. This is made easy by good documentation on the ProcessWire website and a decent set of ‘starter’ template files that come as part of the default install. Conclusion ProcessWire was an absolute dream to work with. Ray found it to be very stable, well thought out and hugely flexible. So much so in fact, that Ray has decided to standardise on using ProcessWire for upcoming web design projects. The flexibility and simplicity of the admin system, combined with power in frontend development that ProcessWire provides is something that Ray found to be liberating and more importantly ‘best in its class’.
    1 point
  30. @Diogo, I haven't had time to test the second version. Will do so sometime. Meanwhile, I have been busy playing with the module and here's a taster...a CRUD system for: a db external to PW (see video) PW pages (attached screenshots) Just fooling around at the moment. It is WIP as I learn the ropes of PW. In these examples I am using jTables. Will soon switch this to the great DataTables. Soma has a module of this one in the forums. Here I show how easy it is to implement using your module Many thanks for your awesome module!
    1 point
  31. Any modules that extend: Inputfield, Process or ModuleJS will auto-load their CSS/JS files if they have the same name as the module and appear in the same directory. However, in order for that to work, their init() method has to be called. So if your module extends one of those, and has an init() method, then make sure to call the parent init() method: public function init() { parent::init(); // ... then your code }
    1 point
×
×
  • Create New...