Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/01/2014 in all areas

  1. A few new/minor additions on the dev branch: You can now paginate with "limit=1" selectors. Previously ProcessWire didn't build the pagination information when a limit of 1 was specified. Now it does. ProcessWire now preloads pages that it knows it's going to need on every request. This speeds up everything slightly, as what was previously done in 6-7 queries is now done in one shot. Should you want to, you can also specify additional preloaded pages, though I don't think many (any?) would need to. Several optimizations to the PageFinder engine which improves the speed of certain types of queries. One of them is a $pages->count("selector") query, which is now even faster than before. Selector Grouping Added support for selector grouping to change the behavior of how they match. This is best explained by example. Lets say we're building a big news site, and we have a template called news-item that represents each news article. Each news-item page has a field called cats that is a multi-page reference to one or more category pages. This is a pretty common scenario in ProcessWire. The site has a lot of categories, so want to designate some categories as featured so that we can display featured categories on the homepage and elsewhere, with accompanying news items. Rather than just adding a featured checkbox, we add two fields to represent the date range that we want them featured: featured_from and featured_to. On our homepage, we want to display articles from all the current featured categories, so we build a selector like this: $items = $pages->find("cats.featured_from<today, cats.featured_to>=today, sort=-date"); ...but we end up with more news-items than we expect, including some that have categories that aren't actually featured right now. Why? Because each news-item can have multiple categories, and that selector above is saying this: The keywords there are "at least one", as "categories.featured_from" and "categories.featured_to" may not be referring to the same category. The only way to solve it was this: $categories = $pages->find("template=category, featured_from<today, featured_to>=today"); $items = $pages->find("categories=$categories, sort=-date"); That's easy enough... but now you can also do it like this, by prepending an @ to identify a group: $items = $pages->find("@cats.featured_from<today, @cats.featured_to>=today, sort=-date"); The "@" symbol at the beginning of "cats" is telling ProcessWire those are grouped together and "these must match the same exact page". This was added because there are situations where you need to perform your query with 1 selector rather than breaking it up. An example would be when used with the new InputfieldSelector module and Lister, among others. We will likely be adding more ways to perform complex matching scenarios with a single selector as well. Currently this "@" grouping applies only to multi-page reference fields, as I'm not sure yet where else it might be useful. It is only supported by selectors that hit the database at present (though will be completing it for in memory selectors as well). Not planning to extend it into that area at this time, but good ideas to think about for the future or for modules. It should already be fixed. If we're talking about the same thing, someone recently posted this to the GitHub issues list and I added their fix on dev. Adrian already knows this because we've been chatting in the GitHub issues queue, but for anyone else reading this, it has also been fixed.
    10 points
  2. Please use Matrix Fieldtype & Inputfield Or the ProFields. FieldtypeJson (module) Álpha I've been busy last 2 weeks with a new fieldtype. I needed a fieldtype that generates JSON strings from CSV (excel data). I needed a way to handle a variable amount of columns & needed a way to manage that data. Wanze & Kongondo already worked on a excel crud module with the excellent Excel-like data grid editor Handsontable and I loved that piece of software. Thank you guys. Handsontable is used in the Inputfield part. What the Inputfield does does: If there's no data in the field, the Inputfield shows you a textarea. You could copy 'n past in CSV text in that field. When you save the field, all data is processed. Processing means: Slice till an x amount of data rows. If minimum amount of columns is not reached, pad the columns till the amount you've specified in the settings If the data contains to much columns, slice the redundant amount of columns. Every data left, is trimmed and sanitized Every numbered string will be converted to integers Saved in 2 formats: 1) json and 2) cvs Server side there's a lot of processing needed to perform all this, that is the reason to set a low amount of data rows. On The Inputfield side, the JSON is generated by Handsontable. So this feels a bit dirty. (Server side it does do all the steps in the above list.) For now it's called FieldtypeJson, but i'm not to keen on this name. Output How to output in your template: $page->fieldname // (string) the table markup $page->fieldname->json // (string) JSON string $page->fieldname->csv // (string) CSV string $page->fieldname->rows // (int) number of rows, not really usefull, but needed internally $page->fieldname->columns // (int) number of columns, not really usefull, but needed internally When to use: If you need a small set tabular json data, and you don't know how many columns it has. If you want to have render tables quicky in your site. When not to use: Store very large sets of query -able data. If you have to rely rely on the data. ( all json is stored in a subfield, and the same for csv ) API Side (JSON): // Json string $json = '[["First Name","Last Name","Company Name","Address","City","State","Post","Phone","Email"],["Rebbecca","Didio","Brandt, Jonathan F Esq","171 E 24th St","Leith","TA","7315","03-8174-9123","rebbecca.didio@didio.com.au"],["Stevie","Hallo","Landrum Temporary Services","22222 Acoma St","Proston","QL","4613","07-9997-3366","stevie.hallo@hotmail.com"],["Mariko","Stayer","Inabinet, Macre Esq","534 Schoenborn St #51","Hamel","WA","6215","08-5558-9019","mariko_stayer@hotmail.com"]]'; $page->of(false); // Turn OutputFormatting of $page->fieldname->json = $json; $page->save(); $page->of(true); API Side (CSV): // CSV string $csv = '"First Name","Last Name","Company Name",Address,City,State,Post,Phone,Email Rebbecca,Didio,"Brandt, Jonathan F Esq","171 E 24th St",Leith,TA,7315,03-8174-9123,rebbecca.didio@didio.com.au Stevie,Hallo,"Landrum Temporary Services","22222 Acoma St",Proston,QL,4613,07-9997-3366,stevie.hallo@hotmail.com Mariko,Stayer,"Inabinet, Macre Esq","534 Schoenborn St #51",Hamel,WA,6215,08-5558-9019,mariko_stayer@hotmail.com'; $page->of(false); // Turn OutputFormatting of $page->fieldname->csv = $csv; $page->save(); $page->of(true); After save, all other subfield are updated. So saving JSON will update CSV and the rows and the columns. And saving CSV will update JSON and the rows and the columns. Saving direct to the fieldname, or saving to both json and csv or saving to the rows & columns wil thow a wireException(). Download: source on github Warning: This Fieldtype is Álpha, don't use it in live projects empty field: paste data: imported data: manage data: settings:
    7 points
  3. Hhhm, not enough time to go much further these days, but interesting stuff this ImageMagick. Imagick can be setup as CMS (Color Management System). I have created a little colorTargetfile and a Testcase with files of different colorspaces, colordepth, with and without embedded ICC-profiles, including Adobe-RGB, ECI-RGB, sRGB, different CMYK and different Grayscale. The RGBs and CMYKs it seems I have covered already, grayscales are on the todo.
    7 points
  4. Not sure if someone already have this, but I just wanted to share it, hoping someone improve it, maybe it's good for a function? It will split long list of pages first top to bottom, then left to right. columns are chosen by you. A | D | G B | E | H C | F | I $columns = 3; // choose number of columns $item = 0; // set counter to zero $num = $pages->count("parent=/branche/"); // use variable for total pages $itemsInColumn = intval($num / $columns); // calculate how many child-pages per column echo "total: ". $num . " | per column: " . $itemsInColumn . "<br />"; // this can be removed if you don't want echo "<div class='left'>"; // left is css: float left foreach($pages->find("parent=/branche/") as $child) { $item ++; // count for each child-page a plus one if($item > $itemsInColumn) { $item = 1; // set back to 1 if total is larger then total in column echo "</div>"; // then end div echo "<div class='left'>"; // and start new float left } echo "<a href='{$child->url}'>{$child->title}</a><br />"; // output my child-page } echo "</div><div class='clear'></div>"; // clear float, end div I know you all must have this, but I am really starting to be afraid asking so I found out by myself
    5 points
  5. ProcessWire is easy to get the hang of. If your going to build sites for clients, you will appreciate the differences soon enough. Come on in, the water is nice. BTW: i just finished moving the last of my client sites off MODx (started on 0.95). Most of them I converted on my dime. I did it because It saves me time and is easier for them to manage content. No more dependance on custom modules to get my sites the way I want. Have most everything I need in the core. Dumped drupal for many of the same reasons too. I used to think lots of great third party modules for *some cms* saved us time. Not so. The upgrade problems alone cost us more than the coding in PW. Learn to code. It's a skill that won't be replaced.
    5 points
  6. Hi! In field settings there's a setting called "Language support / Blank behavior". Set it to "Remain blank".
    3 points
  7. if ($user->language == "default") { Your if statements won't work because $user->language is a Language object. So you could try: if ($user->language->name == 'default') // Or if your values are titles rather than names if ($user->language->title == 'francais')
    3 points
  8. I've used both and pages is the best solution, in my opinion. As Macrura said, the Select AKA Dropdown is only for very simple and small amount of options. What anyone eventually learns is that using pages allows for future expansion, even when you initially think you will only ever need 4 or 5 options. My clients have always liked that they can add options to their fields whenever I use the page method.
    2 points
  9. Adding to Wanze's code... $username = $sanitizer->pageName($input->post->username); $u = $users->get($username); if ($u->id) { $message = "Sorry, that username is already taken..."; } else { $u->addRole('frontend-editor'); $u->save(); } Assumes you already have that role available
    2 points
  10. Using pages for selects: that's your most powerful relational database right there! It gives you access to the whole Page Object or Page Objects that are selected (hence everything about them)...you can even go farther down the rabbit hole...and find out more information about other relations that those selected pages have (other than their relation to the page that has the page field) - their parents, children, etc...This is a very powerful PW feature yet Ryan has implemented it as a very simple, user-friendly and elegant solution... I have never used Select AKA Dropdown - so, no comment...but, horses for courses...
    2 points
  11. Help setting up a way to ask for a credit card first, then process the card for the payment, then post the page. This is probably the trickier one. I have no idea about credit card processing but there have been posts in the forums about processing payments, e.g. using paypal...Others can chip (no pun intended!) in here... I have re-read your post and see payment will be made via paypal. From what I have read in the forums (and I agree with that approach), if you can avoid it, do not handle, take or store credit card details on your site. There are "cheaper" payment gateways that can handle that for you....or redirect users to paypal. Let them deal with the security issues. Anyway, I don't know much about this area so search and/or wait for other responses Help redirecting the user to the newly created page after they have submitted the data through the form builder form. The potential issue with this is when two or more pages have been created at the same time. Creating a page via API is easy though. Redirecting is also easy: $session->redirect($url). I don't know how you are creating your pages but one way to grab the page created by "this particular visitor" is: You could get the sanitized name of the page and save that to a variable as you save the page. If the name has not been rejected, then use that name and the template of that page to grab the newly created page and use that as the $url variable in the $session method..e.g. something like....$pages->get("name=$name, template=my-template"); where $name is the sanitized value you saved in this variable before you saved the page [but only proceed with redirecting the user to the new page if one was actually created! So, you will have to check for a page id. If no id exist, the page was not created and you need to tell the user that]. You don't want to use title to get the new page since titles don't have to be unique. There could be other ways of doing it (using cookies and all that...) but the above is probably simpler...Others here will have better ideas ;-) Automatically create a user and password and assign it to the newly created page. I am not sure about creating a password. Why not ask the user to create their own password when registering? Then, save the page but as unpublished which you will then publish after you receive payment. In this case, there is no need to redirect the user to their newly created page. It is of no use to them anyway until they have made a payment they won't be able to log in. So, I would take them to a "thank you" page, awaiting confirmation and payment, blah blah message.... Creating a user is easy. Have a look at the API docs: http://processwire.com/api/variables/user/ Just my 2p
    2 points
  12. I found this very useful when dealing with my dev and live configurations. Paste and configure in /site/config.php $base_url = $_SERVER['SERVER_NAME']; switch ($base_url) { case "samplewebsite.dev": // LOCAL CONFIG $config->dbHost = 'localhostdb'; $config->dbName = 'processwire'; $config->dbUser = 'root'; $config->dbPass = 'PaSsWoRd'; $config->dbPort = '3306'; $config->httpHosts = array('samplewebsite.dev', 'www.samplewebsite.dev'); $config->debug = true; break; case "samplewebsite.com": // LIVE CONFIG $config->dbHost = 'livedb'; $config->dbName = 'processwire'; $config->dbUser = 'username'; $config->dbPass = 'pAsSwOrD'; $config->dbPort = '3306'; $config->httpHosts = array('samplewebsite.com', 'www.samplewebsite.com'); $config->debug = false; break; }
    2 points
  13. Install the profile exporter module http://modules.processwire.com/modules/process-export-profile/ It creates the install directory and comes with instructions.
    2 points
  14. Hi dees2012 and welcome to PW. Here is a comprehensive writeup from Ryan: https://processwire.com/talk/topic/27-moving-pw-between-staging-and-live-server/?p=63 There are lots of other posts about this: http://bit.ly/1i9iJ3r Hope that helps. Let us know if you have any specific questions.
    2 points
  15. Wanze, I am always doing things like that. I develop web stuff on a local box where I create domain names with my own local top level domain which is a sort of in-family joke about a character I used to do for the kids - and then just massage my host file to point in the right place. When a client wanted to see something I was doing the other day, I happily emailed him a link. "What the hell is dot BEAR?" he replied
    2 points
  16. I've updated the module to support typical pw style pagination: $search_results = $modules->get('ElasticSearch')->search('foo bar', $results_per_page); echo "Total results: " . $search_results->getTotal(); echo $search_results->renderPagination();
    2 points
  17. 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
  18. ElasticSearch does a lot, but the part that is most interesting to me is that it does an amazing job of fulltext search. It's also crazy fast. It can be a bit scary at first so hopefully this module will make it more accessible. I threw together this module pretty quickly, it's more of a proof of concept than anything else at this point. I tried it out on a site with 400 bilingual pages and the search results are much improved over the normal search you would get doing like queries or fulltext queries in mysql. Github page: https://github.com/jdart/ElasticSearchProcessWire I'd love to hear some feedback on how it works for you. It's very new so expect bugs, in particular the mechanism that turns pages into data to be indexed by ES might have some surprises.
    1 point
  19. Modules directory: http://modules.processwire.com/modules/facebook-login/ Github: https://github.com/apeisa/FacebookLogin I didn't have any real reason to build this. I actually started to just browse the documentation of OAuth implementations and discovered that Facebook really does make this easy: http://developers.facebook.com/docs/authentication/server-side/ (header "Example" on bottom of the page) so I decided to implement it. It was also nice way to test the Ryan's method of module that creates page which executes itself (like Ryan's new ServicePages module).
    1 point
  20. You've been using MODX but now you've found ProcessWire. It’s totally amazed you and you can’t wait to get started. But…you are wondering where everything is. If this is you, read on… This guide is primarily aimed at those who are coming in from MODX and wish to know how to accomplish “MODX things” the “ProcessWire (PW) way”. This is not meant to be a full blown PW tutorial. It will focus on some key MODX concepts/tasks and how to accomplish those in PW. It will cover, whenever possible, both versions of MODX - Evolution and Revolution. The guide assumes that you’ve at least logged into a PW site and/or viewed a demo. The Table of Contents mostly reflects MODX terminology. Table of Contents 1. Manager 2. File System 3. Resources 4. Templates 5. Template Variables (TVs) 6. Template Files 7. Snippets 8. Modules 9. Plugins 10. Chunks 11. Miscellaneous 12. Examples - the PW way… a. Template Variables b. Snippets c. Modules d. Plugins e. Chunks 1. Manager In PW, the “manager” is referred to as the “Admin”. The default location of the Admin is www.yoursite.com/processwire. As of PW 2.3, you can rename the Admin to anything you wish during install. Just be careful to remember the name you use or you will be locked out! (If that happens, there are ways to get around it though). Logging into Admin, you will notice a tree just like in MODX. The Admin runs on jQuery UI and as you’ve seen, it is insanely fast! Don’t be fooled by its simple facade. PW is a really powerful CMS, highly extensible and very easy to use. Customising the PW admin is very easy. There are a number of custom themes available. It is also trivial to make yours. Custom Admin themes go into the folder site/templates-admin/. You can have only one theme at a time. On a related matter, if you wish to create a custom Admin page, it is easy to do so. See this thread for more info. 2. File System After installing PW, you will see two main folders; “site” and “wire” in your file system. Site is where all things related to your site reside. This is your playground and will survive an upgrade. Wire houses the Core. You will never have to go into that folder. 3. Resources In MODX, Resources can be many things (documents, etc.). There is no such term in PW. However, the most important “resources” you need to know about in PW are page and pages. Pages are a very powerful concept in PW. Page can refer to your website’s frontend pages, i.e. what can be viewable by your website users. I say can be for a reason. There are many uses for Pages in PW. This can be confusing to newbies but once you get the concept, you will appreciate the power of the system. Just because something is a Page does not mean it has to be viewable. It can have other uses such as a container that holds data for use by other Pages - in this case the Pages do not have to be displayed on the frontend. In fact, everything you see on the PW tree is a Page. That’s right; even the Admin and its components (Users, Roles, etc.) are all Pages! Still confused by Pages? Have a read here. Pages reside in the PW tree - you may have noticed . You can drag and drop pages to move them around. If drag and drop doesn’t work you probably have MySQL 5.0.5.1 installed. Upgrade your MySQL and you are sorted. The root of your site is the uppermost Page in the tree. In the default PW install this is called Home. You can change the name to something else. The default PW install comes with a number of Pages pre-installed. Try editing a Page. All those Fields you see on that Page when under the “CONTENT” tab? They are not default Fields. They are all Custom Fields! Yes, not even the Title! The only required Field for a Page is “name”. You find this under the “SETTINGS” tab on the page edit screen. More about Fields below… Other related stuff: Menuindex: As an aside, if outputting something like a menu, unless you state otherwise, it will reflect the tree hierarchy. Show in Menu: This functionality is covered by the Page status, whether hidden or not. Hidden pages do not get output on menus (more about menus later) unless explicitly stated so using PW API selectors (see below). Menu Title: No such term in PW. You can name your menu items what you wish to name them. Very important: All Pages must be assigned a Template. 4. Templates In PW, Templates mean something slightly different compared to MODX and many other CMS. MODX describes templates as: That is not entirely true of PW Templates. In PW, the term Template is used in the sense of the English definition of the term: PW Templates serve as a pattern for the foundation of your Pages. By foundation, I do not mean the HTML or CSS. Rather, the Template servers as blueprint for your Pages. What is available to the Template is available to the Page that uses it. Templates establish a pattern for the Pages by the inclusion of Fields to the Template. A Template can have as many or as few Fields as you wish. You can create as many or as few Templates as you wish. You can easily change the Template a Page uses when editing the Page. See under SETTINGS. Note that if you have Fields on that Page that are not in the Template you are switching to, those Page Fields will be lost! PW will warn you about this when switching Templates though. OK, so how do you show “Resources to the world”? That will be the work of Template Files which we’ll look at in section 6. 5. Template Variables A powerful feature of MODX is Template Variables (TVs). If you loved MODX TVs you will absolutely adore the PW equivalent. In PW, TVs are known as Fields. You can define your own Custom Fields. In fact, you will need to create your own in most cases. This is because PW does not have any required Field except for “name”. It is perfectly reasonable to have a Page with only the name Field! Many people do add at least a Title Field for such Pages. In the default PW install, the reason you see the Title Field in all Templates is because it has been set as a “Global” Field under the ADVANCED settings of the Field (edit the Field to see this setting). There are many types of Fields to hold all sorts of data - images, texts, urls, passwords, reference to Pages, etc. You can call your Fields anything you wish. You can call the Field for your main content “body”, or “stuff”, or “content” or whatever you wish as long as you follow the naming convention, i.e. “[a-z], numbers [0-9], or underscores (no dashes or spaces)”. Fields are reusable across different Templates. The order in which they appear on your Page follows the order in which they are arranged on your Template. However, it is important to note that: The order in which Fields appear on your page and/or the inclusion of a Field on your Page does not mean that: The Field will be output on the Frontend. The inclusion of a Field on a Page does not automatically mean it will be output; PW does not make that decision for you. It only makes the Field available to you to use as you require. You can output all or none or few of the Fields on your Page. The order in which Fields appear on a Page does not mean the same order will be reflected when you output the Page. You make that decision. Also note that you are able to arrange Fields side-by-side on your Page (via settings on the Page’s Template) to mimic your site’s layout or for other visual/ease-of-use purposes as you edit the Page in the Admin. You can also give each Field a label and a description. These will appear above each Field when editing a Page. In most cases, the content of Fields will be saved directly to the database. In the case of file related Fields, the path to the file will be stored in the database. There are no direct equivalents of MODX TVs “@Bindings” (data sources). These are inherently built into the different types of Fields. Note that you cannot run PHP code within Fields (so no @Eval). This is by design. Fields are a very powerful and much loved concept in PW. Just Google "custom fields cms" and you’ll see what comes up tops. 6. Template Files So far, we've seen that you create Fields, add them to a Template you've created and edit a Page using that Template to input your content into that Page’s Fields. So far so good but how do you output the content to the world? You do this via Template Files. Template Files live in /site/templates/. You have to create your own Template Files. In MODX, a Template will have both system fields, e.g. body, title, etc. and custom fields (TVs). Rendering a Template is achieved by adding MODX tags to your Template. In PW, in order for the content of your Page to be seen by the world, its Template must have a Template File (or there must be some other Template File associated with a different Template that is dynamically pulling and outputting elsewhere the content of a Page whose Template does not have a Template File). This does not mean that all content within a Page will be automatically output by the Template File. No; in the Template File you can choose to render all or some Fields present in the Pages using that Template or none at all! You tell the Template about the associated Template File when you create/edit the Template. PW assumes that there is a Template File with the same name as the Template in /site/templates/ and will tell you if it does not find one. However, you have two other choices. You can either enter an alternative name for your Template File or tell PW you do not wish to have a Template File for that Template. This means that a Template does not require a Template File. Obviously, in such a case, you will not be able to directly output the content of the Pages using that Template. In some cases, that is exactly what you want . As you get to know more about the system, you will find out how powerful and flexible the PW Template system can be. For instance, you can use your Template as a controller. That’s beyond this guide but feel free to search the forums for more info. Template Files are typically PHP files with logic to dynamically output your content. In most cases, Template Files are HTML with PHP tags inserted to output your content. The PHP in the Template File will in most cases be PW API. Hence, you will see things like $page and $pages in Template Files. The former always refers to the current Page and the latter to any other Pages in the system. These are very powerful variables in PW and give you access to ALL information about ALL pages including their Fields and whether those are empty or not, etc. See below for more info about these variables and have a look the docs too. Note that Templates do not care about what’s in your Template Files. In fact, they won’t even check. All they want is for you to tell them if and how you wish your Pages' contents to be rendered. Your Template Files can even contain pure HTML (although that won’t be dynamic!)! Your Template Files can have references to other things related (or not related!) to the Page using that Template File. For instance, within your Template File, you can pull in the 10 latest “posts” from your Blog or the Children Pages of that Page. There are just too many possibilities to list them all here. Don’t let the PHP in Template Files scare you if you are no coder. I am no coder but I am able to use PW. You will only need to know at least some very basic PHP to use PW. The most important are: echo; foreach; and if… Anything else is a bonus in most cases. In addition, you will need to know how to use the two most important PW variables - $page and $pages. With these two, most of what you would have done in vanilla PHP is covered. They are easy to use and to understand and very much follow the jQuery concept. Check out the docs to learn more. 7. Snippets In MODX, Snippets are the method by which MODX allows you to run dynamic PHP code in any of your pages. In PW, the term Snippets does not exist. What!?! Not to worry; in PW MODX-like Snippet functionality can be achieved in two ways: Template Files: Most PW Template Files are essentially dynamic PHP code. That’s Snippets for you right there. PW Modules: PW Modules do what MODX Snippets do and more (see below). It’s just an issue of terminology. For instance, the popular MODX Snippet WayFinder has a Module counterpart in PW. This is the Module Markup Simple Navigation. However, you do not need to use the Module to create a menu in PW. You can do the same thing using PHP in your Template File. See the default PW install for a simple example. Check out section 12 of this guide for example “popular-MODX-Snippets-to-PW-how-tos”. 8. Modules MODX Evolution defines Modules as “a program that can only be executed from within the manager.” There are PW Modules that fit this definition, for instance, the Module Batcher which is equivalent to the MODX Revolution add-on Batcher. However, there are other PW Modules that are executed in the frontend, e.g. Markup Simple Navigation previously mentioned. In fact, in PW, a Module is PHP that extends the functionality of PW. Modules contain PHP classes that adhere to PW’s Module interface. 9. Plugins In MODX Plugins are PHP code that are set to execute during certain system events. In PW, although the term Plugin does not exist (except maybe in reference to Modules), MODX Plugin functionality is easily doable in PW. This is achieved via Hooks. There is one difference though. In MODX, Plugins are standalone code you can download and install. You cannot download and install PW Hooks. Instead, PW contains many methods that you may hook into in order to modify the behaviour of the method. In other words, PW offers the ability to hook into its processes/events and manipulate them before or after the event or even replace them, etc. Hooks are usually invoked inside Modules. However, Hooks may be attached from anywhere that you use PW's API, for instance in Template Files. The average PW user will not need to use Hooks. For more info about Hooks check the documentation. 10. Chunks MODX defines Chunks as “bits of static text which you can reuse across your site”. There is no equivalent term in PW. You can, however, easily create Chunks in PW. You can create Chunks as a Page that contains various Fields each of which can act as a Chunk. This means you can have Chunks of all sorts of data. You can then set the Page you create to hold your Chunks as hidden (not available to searches). The Page can also be assigned a Template without a Template File to further limit frontend access. It can also be created as a child/grandchild of the page Admin. That will limit access by User (e.g. login required to view it in Admin). Accessing the Fields of that Page as your Chunks using PW API is quite trivial really. Since you can use labels and descriptions to further define each of your Pages’ Fields, this makes it quite easy to describe what each Chunk is for and/or give instructions on how to use the Chunks. See this example for more info. You can also simply use text files to pull into your content as Chunks. Personally I prefer using Pages as Chunks when I need to. In MODX, it is usual for many Snippets to use Chunks (HTML + placeholders) to structure their output (i.e. tpl Chunks). You do not need to do this in PW. Code output can be wrapped in HTML right within the Template File. The important thing to remember is that any Field in any PW Page is available to any other Page and any Template File. Cross-referencing Fields and Pages is child’s play. Seriously; it is that easy. 11. Miscellaneous Tag Syntax: PW does not use a templating language (tagging syntax) like MODX does. See this article why this decision was taken. I agree 100% with the approach and have come to realise its many benefits over using a templating language. However, there are two Modules that allow you to use template language tags in PW. I have never used them so cannot comment further. They are here and here. Settings Page: PW has no settings page like MODX. Many settings are set in the /site/config.php. Other MODX settings equivalents are interspersed in various places including caching content on a Template by Template basis and in Modules. You can also store custom settings needed for your site in the /site/config.php. You can even use Pages to store your settings as mentioned in section 10 (Chunks). Modularity: PW is a very modular system. The whole of PW is made up of Modules (Core Modules) that accomplish different tasks. 12. Examples - the PW way… In this section I will show you equivalent MODX versus PW add-ons as well as how to accomplish various task using PW “Snippets” equivalent. a. Template Variables As previously mentioned, MODX TVs are PW Fields (although PW Fields are more versatile). Outputting the contents of your Fields is very simple. echo $page->name_of_your_field; This gives you the contents of the Field in the current page. Works slightly different for image fields though. For other pages echo: One page $pages->get(ID or PATH or NAME, etc.)->name_of_your_field; //note replace ID with ID of the Page you want, etc. Many pages $pages->find("selectors"); //this will return an array. You can then go through the array using foreach as shown in the examples below to output the field(s) contents MODX - output main content of Page //MODX Evolution[*content*] //MODX Revolution[[*content]] ProcessWire - output main content of Page //ProcessWire echo $page->content;//note; this assumes you have a Field called content in the Template of the current page. In ProcessWire you can find Fields of other pages like so $fruits = $pages->find("template=yumyum, limit=10"); foreach($fruits as $fruit) { echo "<li><a href='{$fruit->url}'>{$fruit->title}</a></li>"; } //find 10 Pages that use the Template yumyum and echo their url and titles in a list. From these examples, you can see the elegance and flexibility of TVs done the PW way. Since there is separation between a Template and a Template File, you can conditionally echo out the contents of Fields found in Pages. b. Snippets Common MODX Snippets and PW equivalent Modules 1. WayFinder: Markup Simple Navigation or code in Template File (see head.inc in default PW installation for a simple menu). 2. Ditto (Evolution) and getResources (Revolution): Functionality inbuilt in PW. Use $page and $pages variables + selectors to find anything, anywhere. 3. Jot (Evolution) and Quip (Revolution): Comments Module is part of the PW Core. It is not enabled by default. You will have to enable it in the Admin. See also the related Comments Manager Module. 4. eForm (Evolution) and FormIt and FormItBuilder (Revolution): There are various Form parser codes in the Forums. There is also a commercial Form Builder Module. It’s not expensive, is developed by PW’s lead developer and proceeds support the PW project. 5. MaxiGallery (Evolution) and Gallery (Revolution): Presently, there is no equivalent. However, it is quite easy to build a photo album. See this tutorial in the wiki. There is also an Images Manager Module (still in alpha though). 6. AjaxSearch: Ajax Page Search Module. 7. Breadcrumbs: Quite easy to accomplish using PW API. See default PW install for an example. 8. FirstChildRedirect: Very easy to do using PW API like this: $session->redirect($page->children->first()->url); in a Template File. 9. getField (Evolution) and getResourceField (Revolution): Inbuilt in PW $page and $pages variables as shown above. 10. GetParent: Inbuilt in PW $page and $pages variables. E.g. $page->parent. 11. getPage: PW has inbuilt pagination as part of the Core (Pagination Markup Module). See this article for a quick tutorial. 12. UltimateParent: Inbuilt in PW API as rootParent. 13. if (Revolution): Use vanilla PHP with PW variable and selectors in Template Files. 14. VersionX (Revolution): Versioning for text-based fields is coming in PW 2.4 (release date summer 2013). Support for maintaining separate draft and live versions coming in PW 2.5 (Winter 2013/2014). Currently, there is also the Module Version Control for Text Fields. 15. getRelated (Revolution): No out-of-the-box Module for this. Has been previously accomplished using PW API in various ways. Have a look in the forums. 16. importX (Revolution): Import Pages CSV Module. 17. phpThumbOf: Thumbnail functionality is inbuilt in PW. There is also the Module Thumbnails that further extends this functionality. 18. getValue and getValues (Revolution): Inbuilt in PW. You can get the value of any Page using PW API - $page and $pages. 19. getFeed (Revolution): RSS Feed Loader Module. 20. MIGX (Revolution): Repeater Module which is part of the PW Core. It is not installed by default. You will need to do that yourself. For more info see this tutorial. 21. Articles (Revolution): See the Blog Profile Module. 22. NewsPublisher (Revolution): See below under Plugins. Examples MODX Ditto [!Ditto? &parents=`5`&extenders=`summary` &tpl=`tplBlog` &orderBy=`createdon ASC`&display=`6` &truncText=`Continue Reading This Article` !] PW equivalent $items = $pages->get(5)->children("sort=date,limit=6"); foreach ($items as $item) { echo $item->title; echo $item->summary;//etc. } //this assumes you have a Field called summary on that Page The first line in the above gives you all information about the 6 child Pages of the Page with ID #5. It returns an array. In other words, a basket of various documents containing all the info about those documents. Next, you traverse the array using foreach. In layman terms, you rummage through the basket picking goodies! In order to wrap HTML around the code output, we do it like this instead (there’s other ways to do it as well!) echo "<ul class='articles'>"; foreach($pages->get(5)->children("sort=date,limit=6") as $item) { echo "<li><p><a href='{$item->url}'>{$item->title}</a><br /> <span class='summary'>{$item->summary}</span></p></li>"; } echo "</ul>"; In this example, we have asked PW to grab the child Pages directly within the foreach rather than creating a variable $items first. MODX getResources // Output a list of child Resources of the current Resource, using the 'myRowTpl' chunk: [[!getResources? &parents=`[[*id]]` &tpl=`myRowTpl`]] PW equivalent echo "<ul>"; foreach ($page->children as $child) { echo "<li><a href='{$child->url}'>{$child->title}</a></li>"; } echo "</ul>"; //You might want to limit the number of child Pages you are getting if they are many! MODX getResources // Output the top 5 latest published Resources beneath the Resource with ID '5', with tpl 'blogPost': [[!getResources? &parents=`5` &limit=`5` &tpl=`blogPost` &includeContent=`1`]] PW equivalent echo "<h3>Latest Posts</h3>"; $posts = $pages->get(5)->children("limit=5"); foreach ($posts as $post) { echo $post->body; } c. Modules 1. Batcher and Docmanager (Revolution): Batcher Module (covers most equivalent functions). 2. DocFinder (Evolution): Inbuilt in PW default install. d. Plugins 1. QuickManager (Evolution): Several Modules can do this, i.e., Fredi, Page Frontend Edit and Inline Editor Modules. 2. ManagerManager (Evolution): Same functionality can be achieved using Templates, Access Control and the Modules Page Edit Field Permission, Page Edit Per User and Page Edit Per Role. e. Chunks See this example. Btw, the PW Cheat Sheet is you best friend... Hope this has been helpful! /kongondo
    1 point
  21. Launched just a few days ago: http://yummimami.de - a presentational website for a German startup supplying healthy and kid-compatible presented food to schools. Some features Responsive Forms via FormBuilder Navigation via MarkupSimpleNavigation (which, at least in my use case, evolves into something super essential for PW - like Views for Drupal for example ) Widget handling via having a big pool with pages of template type "widget", then referencing (and hence, rendering) them on content pages Editorial influence on the homepage teasers main color via SVG + field + ColorPicker (not necessary to that extent since the customer doesn't need to change the color to any other that magenta, green or brown - but still: proof of concept)
    1 point
  22. And just because I am procrastinating, if the role doesn't already exit: $newrole = new Role(); $newrole->name= 'frontend-editor'; $newrole->addPermission('guest'); $newrole->addPermission('editor'); //or whatever permissions you need it to have $newrole->save(); $u->addRole('frontend-editor'); $u->save();
    1 point
  23. find will find many (or even all!) things if they exist unless you limit it. This will put a strain on your servers and PHP may even timeout. get, will only get one thing...so, less resource hungry. The general rule is that when using find, you need to use limit=xx. You can always paginate your results if you need more to be fetched. But, if you are sure that the number of children will not grow, and that you have a set reasonable number of children, then you can avoid the limit
    1 point
  24. Figured it out $field->attr('value', is_array($data['subscriber_number']) ? $data['subscriber_number'] : array());
    1 point
  25. using pages for selects is better, unless it's a situation where you have a tiny # of options and no difference between the displayed value and the actual value
    1 point
  26. First you should confirm that mod_rewrite is active. This should work for you (remove comment #). # RewriteRule ^pages/ / [L,R=301]
    1 point
  27. Edit: Here's some code. Note, I am using a URL field...works fine... if ($page->links) { echo "<p>The existing short url is :" . $page->links . "</p>"; } else { require_once('Googl.class.php'); $url = new GoogleURL('YOUR_API_KEY'); // Shorten URL $shortUrl = $url->shorten($config->httpHost . $page->url); $page->of(false); $page->links = $shortUrl;//this is a URL field $page->save('links');//we save only this field (see Adrian's post below) echo "<p>The shortened url is :" . $page->links . "<p>"; }
    1 point
  28. You could do something like if (!$child->seasonal) { Nothing to see here }else{ all my lovely results } If you want to display if it IS selected, then do not do if ($child->seasonal==1) { but rather if ($child->seasonal) {
    1 point
  29. I think you have to "unselect" the Parent of selectable page(s).
    1 point
  30. Oh, as simple as that Thanks Fokke. There is always a surprisingly easy way with PW. Great!
    1 point
  31. If you add temporary code, to delete certain pages, to the templates/admin.php: remember to remove it afterwards to avoid headaches, facepalms and keep you healthy. Actually happened a couple times already, I'm getting older too.
    1 point
  32. Did things get a little grizzly after that exchange?
    1 point
  33. I just tried 40 minutes to connect to a DB server via a python script, always getting errors that no host is available.... until I finally realized, that the IP used was not public and I needed a VPN connection first.
    1 point
  34. Just don't specify a parent. It's not mandatory if you have template or selector.
    1 point
  35. This is what I do to avoid accidents if ($input->get->kill == "yes") { // do dangerous things }
    1 point
  36. The best one I ever did (many, many years ago) was to reformat a disc. I studiously backed up the contents to another drive and then reformatted the entire disc. I can't remember exactly what the point was when I remembered that the other drive was in fact just a partition of the same disc.....
    1 point
  37. Here is the fastest 5 step template tutorial, but it is how it works: 1, Create a file in site/templates called mytemplate.php 2. Go into admin, go to template and create a new one - you will see your mytemplate.php listed. Click the checkbox and save. 3. Go to pages in admin, click on home and click on New to create a new page. Select your mytemplate template and put something in the title field. Save and then publish. 4. Open your very empty template files and write the following <?php echo $page->title; ?> Save it. 5. Go to the front end of the site - if you have used just the default installation you will see your new page in the top menu. Click on it. and you will see a very boring title on a very plain page. And that is the totality of the template system - the rest is up to your html and css imagination! Good luck.
    1 point
  38. is Travel_escapes the checkbox field? If that is the case, your code doesn't work because you are treating it as an array. This should work: if ($child->Travel_escapes < 1) { or even: if (!$child->Travel_escapes) {
    1 point
  39. Here are a few ProcessWire sites I've launched in the last month or so. Nothing real big or exciting here, but figured it's good to post new stuff here when available. Blue Ridge Beverage This is a beer distributor for the state of Virginia in USA. I designed it back in 2009, but the client only recently came back and wanted it developed and launched. A friend did most of the development and did a great job getting everything working in ProcessWire. The client is still populating content here, so there are a few holes, especially in the Beverages database. Almanac of Architecture & Design Before you click on this one, note that this is using the default ProcessWire "basic site" profile (the client fell in love with it and didn't want to change… what can I do). But don't let that fool you, because this is actually quite a large and comprehensive site, particularly the Architecture Firms database. This one has dynamic maps, graphs, search engines and stats galore. There's also some fun stuff in the Buildings section. This site is an on-going project, so some sections are built out more than others, and stuff will be continually added to it. Jamaica Villas I just did the development on this one (not the design, other than tweaks). The design they had was very much in line with the Kickstart framework, so I stuck with it when producing in ProcessWire. I enjoyed using it, and was nice to use a framework developed by another ProcessWire user. I've worked on a few other villa sites in the past, and this one is smaller in terms of quantity of properties, though still involved a lot of work. This one has a full calendar and availability tracking system built into it (all running on ProcessWire), so it can search by availability or look at availability calendars and such. So there's a lot of power packed into this one. I just wish I'd had the opportunity to do the full design on this one, but it was still a satisfying and enjoyable project (as most are, when using ProcessWire)
    1 point
  40. Hey, over a year ago I build the website for the bar "Kapitl21" which is really close to where I live in exchange for a beer flat (<- was my idea ). I completely forgot to post it here. Hope you guys like it: http://kapitel21.de / Nico
    1 point
  41. I am not sure on the whole GD vs Imagemagick quality issue. I know years ago IM was ahead, but not sure if that is still the case. From reading around it sounds like they each have their strengths and weaknesses. That said I have always used IM until I started using PW. For the sake of experimenting, I quickly threw this module together as a way to test IM within PW. It replaces the resize method, so it will work from the admin and also template calls like: $image->size(400,0) It doesn't do anything more than the resizing at the moment - it currently ignores all quality settings, cropping etc. I doesn't try to do any sharpening either, but it's a starting point that we can play with. I need to get back to real work, but thought one of you guys might be keen to play around with and tweak settings and see what you can come up with. Obviously you need imagemagick on your server and also the iMagick extension. ImagickResizer.module
    1 point
  42. When you say you have a tmp directory at the root, do you mean the root of your site, or the root of your server? It needs to be the latter. Otherwise, have you tried following those instructions? Create this folder: /site/assets/uploads/ and set its permissions appropriately. Then in your config.php file, enter this: $config->uploadTmpDir = dirname(__FILE__) . '/assets/uploads/'; That should work - let us know how you go. PS alternatively, you could point that config directive to the /tmp directory if it is at the root of your site.
    1 point
  43. Hi Bbeer, you can try the sharpening option values: $options = array( 'cropping' => 'center', 'sharpening' => 'medium' // none | soft | medium | strong ); You may also check your default setting in the site/config.php file: $config->imageSizerOptions = array( 'upscaling' => true, // upscale if necessary to reach target size? 'cropping' => true, // crop if necessary to reach target size? 'autoRotation' => true, // automatically correct orientation? 'sharpening' => 'soft', // sharpening: none | soft | medium | strong 'quality' => 90, // quality: 1-100 where higher is better but bigger ); EDIT: if you want to test out different settings, remember to use $thumb->removeVariations() before creating the new thumb.
    1 point
  44. Thanks kongondo, so I got myself an account on GitHub now and posted the issue: https://github.com/ryancramerdesign/ProcessWire/issues/383
    1 point
  45. Yes, but it is free membership. The advantages of filing at Github are: 1. Ryan will definitely see it 2. Changes can be tracked 3. Progress can be followed. I am not saying that Ryan will not pick it up from here; but there are chances that he can miss it too. On the other hand, a verified bug can also be filed on your behalf by someone with a Github account in these forums. Finally, you don't have to be a dev or module contributor to join Github
    1 point
  46. Yes, anything that you are inserting into HTML. For instance: <input type="anything" value="this needs to be entity encoded" /> <input type="anything" any-attribute="this needs to be entity encoded" /> <textarea>this needs to be entity encoded</textarea> <h3>this needs to be entity encoded</h3> (The text "this needs to be entity encoded" is the user input, not the tags) Anything in HTML like this needs to be entity encoded, unless you want the browser to interpret it as markup. Usually you don't want user input to be treated as markup by the browser, because it gives them control over the page.
    1 point
  47. A simple rule to remember is: Any data input from the user needs to be entity encoded before outputting it back to a browser. What is entity encoding? It means taking some special characters and converting them to a format that isn't interpreted by the browser as anything but text. We care primarily about characters used for tags, like "<" and ">", characters used for single or double quotes (especially when values might end up in HTML tag attributes), and ampersands "&". These are the characters that can mean something more than just text to a web browser. But you don't even have to think about this if you just remember to entity encode any output. There are cases where you don't have to entity encode, like if you've already typecast something as an integer, or already run it through one of PW's filtering functions that removes special characters... $sanitizer->pageName() is a good example. But if you want to play it safe, just entity encode everything you are outputting back to the user... there's no harm in it. One way to tell if entity encoding is working is to enter a value like "<b>test</b>" in your form field. When you get it back, if it reads as test rather than <b>test</b>, then you've got a problem. No. $sanitizer->text() filters input for storage, not for output. It limits length and prevents linebreaks, among other things. While it strips tags (unless you tell it not to) it doesn't entity-encode any characters. The reason is that you don't usually want to store entity encoded text, unless it's meant to be stored as markup, like TinyMCE (in which case, none of this applies). So ideally, your sanitization would go something like this: // these values are for API use or storage $firstName = $sanitizer->text($input->post->first_name); $lastName = $sanitizer->text($input->post->last_name); // these values are for output back to the user $outFirstName = $sanitizer->entities($firstName); $outLastName = $sanitizer->entities($lastName); // you might prefer to bundle these into an array When it comes to outputting values that came from the user, the $sanitizer->text(); is certainly a good idea, but it's not required. It's not going to make the text any safer for output than $sanitizer->entities(); will on it's own.
    1 point
  48. Just wanted to reiterate what Wanze said about this: <input type='text' name='first_name' value='{$input->post->first_name}'> This is a major security hole. For example, try submitting this in the first_name field: '><script>alert('Gotcha!');</script> ...and if you can do that, you can do some pretty bad stuff. Definitely entity encode user submitted input that gets output again. Wanze's example: $v = $sanitizer->entities($input->post->first_name); echo "<input type='text' name='first_name' value='$v'>"; If you are running an older version of PW that doesn't have the $sanitizer->entities() method (a fairly recent addition) then do this: $v = htmlentities($input->post->first_name, ENT_QUOTES, 'UTF-8');
    1 point
  49. Preview of RC1. https://youtu.be/PIgUMLZEcIU almost ready, time for bugfixing .
    1 point
×
×
  • Create New...