Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 12/06/2012 in all areas

  1. Hey PW, I am only a starting developer and I am still in school and my experience with processwire is quite small but recently I've created my own module for Processwire and I kind of had to ask and copy a lot from other sources, now I want to create a small walk through tutorial for people with the same lack of knowledge as me And as a guide for myselfs in the future 1) Setting up the file. Okay, so we start of by making a new document in the Module root folder and call it Harmster.module for this example, we dont need to add the .php extension. Now every module in Processwire needs to extends the classes and methods from Processwire itselfs so we start off by typing class Harmster extends Process{ } You can also extend WireData, I don't really understand the difference but both work for me A module contains 2 standart classes, init() and getModuleInfo() init() This is kind of, or the same as a __construct() method, this always executes and is executed almost at creation. getModuleInfo() This is a method that is used to show the information in the Processwire CMS. We both need to add these to our fresh class like following: class Harmster extends WireData { public static function getModuleInfo() { return array( 'title' => 'Harmster', 'version' => 100, 'summary' => 'Harmster module' 'singular' => true, ); } public function init() { $this->setFuel("harmster", $this); } This is where I, as a starting developer, get really excited about this little code in the init() method $this->setFuel("harmster", $this); Basically creates your class in every template you are going to use and it is callable by $harmster Woah! awesome right! Now this is where I got stuck on, I the user to configure some options in the module :\ hmm... Well I just went asking on the forums and the super nice community of PW came to help me, Wanze in this case (no emoticon because its not allowed) (Check it for yourselfs, http://processwire.c...lds-for-module/) And basically you need to implement some methods from an another object, you should replace this, class Harmster extends WireData implements Module with class Harmster extends Process implements Module, ConfigurableModule But when you add that and try to use your module you'll see you get an error, we need to add one more method to the class called getModuleConfigInputfields add static public function getModuleConfigInputfields(array $data) { } 2) Adding a configurable and usable textbox But now you want to add some input fields, now this is pretty hmm complicated For a simple textbox you put this inside the method you just made: $modules = Wire::getFuel('modules'); $fields = new InputfieldWrapper(); $field = $modules->get("InputfieldText"); $field->attr('name+id', ''some_text_field_saved_name''); $field->attr('value', $data['some_text_field_saved_name']); $field->label = "Hamsters rule!"; $field->description = 'Enter a nice sentance here if you like hamsters'; $fields->append($field); Now you've created a input field and you can use it with $this->get(''some_text_field_saved_name''); in all your methods in this class (no emoticon because its not allowed) If you're lazy Now what you've created is a configurable module, heres a I am lazy and i want to pastey (no emoticon because its not allowed) class Harmster extends Process implements Module, ConfigurableModule { public static function getModuleInfo() { return array( 'title' => 'Harmster', 'version' => 001, 'summary' => '', 'href' => '', 'singular' => true, 'autoload' => true, ); } public function init() { $this->fuel->set("harmster", $this); } static public function getModuleConfigInputfields(array $data) { } } Now if you want to add a overview page, much like the setup, pages, acces and module tab in Processwire CMS default you can easily do this by adding 2 new methods in your class, install and uninstall 3) Creating your install and uninstall So you want to get a nice overview for your module now eh? Well we can do that because Processwire is awesome like that I did this for my module Now, we need to add 2 methods to our class, ___install and ___uninstall (yes, 3 underscores) So add this to your class: public function ___install() { } public function ___uninstall() { } I think that these are kind of self explaing, the one method gets executed when the user installs the module and the other one gets executed when the user deinstalls the module. Now we want to add a page to PW CMS, but how (no emoticon because its not allowed) Thats actually really easy, $page = $this->pages->get('template=admin,name='.self::PAGE_NAME); if (!$page->id) { $page = new Page(); $page->template = $this->templates->get('admin'); $page->parent = $this->pages->get($this->config->adminRootPageID); $page->title = 'MailChimp'; $page->name = self::PAGE_NAME; $page->process = $this; $page->save(); } This is how you install a page, notice that we name the page to self::PAGE_NAME therefor you want to add const PAGE_NAME = 'harmster-module'; with the name of your module BUT BUT now everyone can look in to this module D:< i dont want that! Ofcourse you dont want that. Clients are famous for breaking everything where they put their hands on, so we need to create permissions! Now the way you make permissions is just genius and so easy, you just add this to your ___install method, $permission = $this->permissions->get(self::PERMISSION_NAME); if (!$permission->id) { $p = new Permission(); $p->name = self::PERMISSION_NAME; $p->title = $this->_('View Harmster Page statistics and synchronize pages with lists'); $p->save(); } And you create a permission constant just like PAGE_NAME like this const PERMISSION_NAME = 'hr-view'; And of course you can create more permissions, just genius! Now what our install method should look like is this: public function ___install() { $page = $this->pages->get('template=admin,name='.self::PAGE_NAME); if (!$page->id) { $page = new Page(); $page->template = $this->templates->get('admin'); $page->parent = $this->pages->get($this->config->adminRootPageID); $page->title = 'Harmster'; $page->name = self::PAGE_NAME; $page->process = $this; $page->save(); } $permission = $this->permissions->get(self::PERMISSION_NAME); if (!$permission->id) { $p = new Permission(); $p->name = self::PERMISSION_NAME; $p->title = $this->_('View Harmster Page statistics and synchronize pages with lists'); $p->save(); } } This will set a module page up for you And we create an uninstall method, this basicly reverts your installed permissions and pages. public function ___uninstall() { $permission = $this->permissions->get(self::PERMISSION_NAME); if ($permission->id) { $permission->delete(); } $page = $this->pages->get('template=admin, name='.self::PAGE_NAME); if ($page->id) { $page->delete(); } } Now you are might be wondering, how do i get to display content in my page :S Well, I kinda stole this from other modules and it does work, but I am open for suggestions. the method ___execute gets executed when you click on your page in the PWCMS. What i wrote in there is public function ___execute() { return $this->_renderInterface(); } and in renderInterface() i put the next code: private function _renderInterface() { $this->setFuel('processHeadline', 'MailChimp synchronize tool'); $form = $this->modules->get('InputfieldForm'); $form->attr('id','ga_form'); $wrapper_audience = new InputfieldWrapper(); $field = $this->modules->get("InputfieldMarkup"); $field->label = $this->_("Gebruikers"); $field->columnWidth = 100; $members = $this->list_members($this->get_apikey()); $html = "<table class='AdminDataTable AdminDataList AdminDataTableSortable'>"; foreach($members['data'] as $member) { $html .= "<tr><td>" . $member['email'] . "</td><td>" . $member['timestamp'] . "</td></tr>"; } $html .= "</table>"; $field->attr('value',$html); $wrapper_audience->append($field); $form->append($wrapper_audience); return $form->render(); } Bascily you create a form and you render the form and that displays it for you, just play around with it for a bit and you'll get into it, as i am still getting into it. I am lazy, here a copy, pastey (no emoticon because its not allowed) <?php class Harmster extends Process implements Module, ConfigurableModule { const PAGE_NAME = 'harmster-module'; const PERMISSION_NAME = 'hr-view'; public static function getModuleInfo() { return array( 'title' => 'Harmster', 'version' => 001, 'summary' => '', 'href' => '', 'singular' => true, 'autoload' => true, ); } public function init() { $this->fuel->set("harmster", $this); } static public function getModuleConfigInputfields(array $data) { } public function ___install() { $page = $this->pages->get('template=admin,name='.self::PAGE_NAME); if (!$page->id) { $page = new Page(); $page->template = $this->templates->get('admin'); $page->parent = $this->pages->get($this->config->adminRootPageID); $page->title = 'Harmster'; $page->name = self::PAGE_NAME; $page->process = $this; $page->save(); } $permission = $this->permissions->get(self::PERMISSION_NAME); if (!$permission->id) { $p = new Permission(); $p->name = self::PERMISSION_NAME; $p->title = $this->_('View Harmster Page statistics and synchronize pages with lists'); $p->save(); } } public function ___uninstall() { $permission = $this->permissions->get(self::PERMISSION_NAME); if ($permission->id) { $permission->delete(); } $page = $this->pages->get('template=admin, name='.self::PAGE_NAME); if ($page->id) { $page->delete(); } } public function ___execute() { return $this->_renderInterface(); } private function _renderInterface() { $this->setFuel('processHeadline', 'MailChimp synchronize tool'); $form = $this->modules->get('InputfieldForm'); $form->attr('id','ga_form'); $wrapper_audience = new InputfieldWrapper(); $field = $this->modules->get("InputfieldMarkup"); $field->label = $this->_("Gebruikers"); $field->columnWidth = 100; $members = $this->list_members($this->get_apikey()); $html = "<table class='AdminDataTable AdminDataList AdminDataTableSortable'>"; foreach($members['data'] as $member) { $html .= "<tr><td>" . $member['email'] . "</td><td>" . $member['timestamp'] . "</td></tr>"; } $html .= "</table>"; $field->attr('value',$html); $wrapper_audience->append($field); $form->append($wrapper_audience); return $form->render(); } } I'll update this tutorial in the near future as i am still working my way up (no emoticon because its not allowed) Aww, i get an error when i save it, thats not nice. Thanks for reading (no emoticon because its not allowed)EDIT Updating this tutorial very soon, its horrible and incorrect
    6 points
  2. I think the new look is fantastic, and just what the project needed. The new design, as others have mentioned, is modern, fresh, and more in tune with current design aesthetics. This is not to say I didn't like the previous design, which I loved, but I think this new look really gives it an edge. Typography and colours look superb on the iPad with retina display, and the buttons in the homepage look attractive and enticing. I also think, as someone mentioned, that the focus on ProcessWire's main selling points is an absolute winner. It lets visitors know, at a quick glance, what the system is all about. The icons used to present this information are also very appropriate, as they provide extra relevant information to help visitors process all the info immediately. So, congratulations to those who worked in the new look, you did a great job. Claudio
    6 points
  3. I have some news about the potential conference in 2013. When I posted about this originally, I didn't know that we had another baby girl on the way, due around May. I am very happy about this, but it would also interfere with my ability to attend a conference. The baby would be too young to travel, and it's too much for me to ask my wife to be alone with a newborn + a 3-year old, while I travel across the world. So I have to put this conference plan on a back-burner while we figure out a better time to do it. Thank you for all of your interest in this conference. I'm really thrilled at all the enthusiasm this conference idea has received, lets plan to reschedule.
    4 points
  4. Have a look at those sad panoramas at http://panorama.philippreiner.de/ It's just a little idea I've had this afternoon. I wanted to post easily from my iPhone to a Processwire installation without using the admin backend* (*= Because I have to login, navigate to the site, click through pages,...) I'm using the tumblr iOs App to post to a Tumblog. (Screen) . Now I'm using apeisas Data Import to get the data from the Tumblr API . I'm using the old v1.1 API because the XML is easier to fetch. The posts are now saved to PW Because I wasn't able to programm a better solution, I'm downloading the images from the URL stored in a field to the original images field. I can now use the PW image functions. Now I can use them as normal pages, do the simple template and start posting. Only problem, the images from tumblr are resized down to 1280px on the long edge. Also, the site is responsiv and the images are loading with lazyload using a <noscript> fallback for older browsers.
    3 points
  5. And that is to have a job board where people who need help with some aspects of ProcessWire that should really be handed by folk who know what they're doing with the API and PHP. Hint: I've got some jobs on that I could do with some help with. I know some of you work full time elsewhere so it'd be great to be able to post a request for paid help - this is client work after all. And because I don't want to have to use anything else except PW! Regards Marty
    2 points
  6. I was in doubt if I should post this one because it's not completely ready. The site is for a thesis project of a friend. In short, he collects raw videos filmed by the random citizen in the Historical Center of Oporto to further analyze and contextualize them. The videos are being submitted on the site, uploaded to youtube and shown on a big random wall. The project will be rethought, and might change a lot in the future. I guess that's why I decided to post it now... PW has a big part on this since every video that is uploaded to youtube is kept as a PW page and connected to a filmmaker (also pages). This allows me to collect all the videos quickly without the limitations that are imposed by requesting with the youtube API, and allows me to keep much more information for each video than YouTube Would. It was also very easy to create a script to import some videos that were already on youtube to the system. PW rocks http://museudoresgate.org/
    2 points
  7. hi ryan, this piece is by former modx fanboys, who converted to pw recently. it's made in interview style and the guy who is mainly talking had pw on his shortlist for a while. since pw was awarded by cmscritics recently, they now decided to publish the interview. their first topic is how easy it is to update pw compared to modx. they continue with their opinion, that modx is more "academic" while pw is made by people who know webdesigner's everyday business. next they praise how responsive the main developer of pw is (do you know him?). good ideas raised in the forum make their way into the core quickly, they state. next they talk about the simplictiy of pw. they raise questions on the roadmap: will pw stay as simple as it is? or will it go the "enterprise road" like modx did? the piece is not at all an introduction to pw. it's more a fireside chat of people who know modx in detail and now compare it to pw. they end with a chat about the api. that everything in pw has to bee done "manually" in pw (with some php knowledge), is a major advantage from their point of view. however, they consider pw as not "sexy" but powerful. the whole thing is a bit like pirate radio (do you say so in english?). i mean independent radio by amateurs. cheers, christoph
    2 points
  8. Fantastic work, I love big and bold.
    2 points
  9. I added the forum and one other: - I may even find time to move some topics around
    2 points
  10. ryan - congrats, and this is obviously the only sensible way to be in two places at once:
    2 points
  11. a basic approach I like: files: global.inc ( here you could place your "global" function & variables ) template-file.php ( include the global.inc on top & default.inc on the bottom ) default.inc ( contains the site HTML & placeholder $variables like $meta_description, $headline, $content ) So in global.inc you could place your switcher function. I use the global.inc for: putting scripts & styles everywhere needed in the config styles & scripts array. setting default values creating empty Variables like: $content = ''; ( that way I know I can start in the template with $content .= 'some string data'; ) Some functions reusable functions. template-file.php: <?php include (./includes/global.inc); $headline .= "<h1>$page->get('headline|title')</h1>"; $content .= $page->body; etc. include (./includes/default.inc); default.inc: Almost static HTML file with the $headline, $content etc. variables
    2 points
  12. short summary: michaels article is a profound introduction to pw, written with practical knowledge. he covers all main aspects such as pags, templates, fields, related content etc. he strongly recommends pw to everybody who likes to have total control over markup and functionality. he points out, that beginners with little php knowledge are good to go in less than one day. that pretty much is it. however, he is not the first praising pw in germany: http://www.perun.net...fs-wesentliche/ ah, just realized that the august article is also by michael ... (it says "vladimir" in the meta information)
    2 points
  13. Couldn't resist a modicum of silliness:
    2 points
  14. I've used Fontdeck, Google Fonts and Typekit, and have to say all three have been pretty reliable. In terms of font selection, there's no doubt Typekit has the edge here. Then, Google Fonts is really attractive not only because it's free but also because it's got some very attractive fonts, like Lato, for example, which I'm currently using on my own site. Fontdeck is also great, but their pricing structure doesn't work well for me, as you have to pay for fonts in an individual basis (Proxima Nova Light, Proxima Nova Regular and Proxima Nova Semibold would be considered as three fonts). I'm also not a huge fan of Typekit's dependency on Javascript. So, I use Google Fonts whenever I can but rely on Typekit when I need a wider font selection. Claudio
    2 points
  15. For a little bit of fun, I have written an alternative (and possibly inaccurate) overview of ProcessWire. https://sites.google.com/a/stonywebsites.co.uk/cms-notes/ It is on the front page. Joss Well, I like to give the customer his money's worth http://www.foodloversdiary.com (the salmon recipe would have gone up, but it got eaten before I could grab my camera!)
    2 points
  16. Michael van Laar was kind enough to make a vectorized version of the ProcessWire logo with several variations, and he sent them to me. This is the first time the PW logo has existed in a vectorized format. Now I'm thinking I need to have some coffee mugs, hats, t-shirts, or airplane banners made. Attached is a ZIP file of the logos he put together, in case anyone wants them to make their own "powered by ProcessWire" banner or anything like that. This will probably become part of a more formal media kit at some point. ProcessWire-logo-michael.zip
    1 point
  17. This module creates a page in the ProcessWire admin where you can test selectors and browse page data and properties without editing a template file or a bootstrapped script. Given selector string is used as is to find pages - only limit is added, if given. Errors are catched and displayed so anything can be tested. Pages found with a valid selector are listed (id, title) with links to the page. I was thinking this would be useful for someone new to ProcessWire, but it turns out I'm using it myself all the time. Maybe someone else finds it useful as well. Module can be downloaded here: https://github.com/n...essSelectorTest Modules directory: http://modules.processwire.com/modules/process-selector-test/ Features Edit selector string and display results (and possible errors as reported by ProcessWire) Explore properties and data of matching pages in a tree viewLanguage aware: multi-language and language-alternate fields supported Repeater fields and values Images and their variations on disk More data is loaded on-demand as the tree is traversed deeper Quick links to edit/view pages, edit templates and run new selectors (select pages with the same template or children of a page) Page statuses visualized like in default admin theme Add pagination Screenshots
    1 point
  18. The idea behind the jobs forum is for anyone looking for paid development work to post their requirements in one place and for developers to get in touch with them. Any project can be posted, whether it's custom development work, website design, or complete installation and setup of a website. There are a few guidelines that are useful to bear in mind to help things go smoothly: Give a good amount of detail about the project so that prospective developers know roughly what will be involved. If a project requires an NDA for any reason, try and give non-specific details such as the type of development work involved (module development etc). Let people know how to contact you - if no contact details are given, people will most likely PM you on the forums here. If you have a requirement to work with a developer in the same country as you, please mention this to narrow the field of applicants. If you are happy mentioning a budget in the open, this is also fine but not required.
    1 point
  19. http://drshackleton.com/ Processwire strikes again!
    1 point
  20. The method I often use is very similar to what Martijn posted. I'm thinking about adding a new $config variable where we can specify what files should be automatically included before a template is rendered. That way we don't even have to do remember to do an include("./global.inc"); The result would be kind of like an autoload module, but one wouldn't have to know how to make a module to benefit from it.
    1 point
  21. If you point me in the direction of those other suggestions I can do them all in about 5 minutes. I'm struggling to keep up with all the new posts made here daily at present, but I'd be happy to oblige with some new forums! EDIT: Ah, guess one of the others is this: http://processwire.c...page__hl__forum I've added Module/Plugin Development as a sub-forum of the existing Modules/Plugins forum (made sense to me) as well as adding a Jobs forum which I think fits just above the Showcase and Pub forums. Any more?
    1 point
  22. phew~ I was curious and clicked through using gibberish, pressing that final 'next' button inadvertently... But I have to say about the site... I LIKE IT!
    1 point
  23. I just tested this proposed gravity like cropping hardcoded in ImageSizer.php I have not done any proper implementation using the options array yet, just some dirty hacking, but it seems to work. For a proper implementation we should reflect the cropping direction in the generated url too I guess? But the math part was simple like this. This code replaces line 208 - 211 in ImageSizer.php of the dev branch: btw, I replaced "imagecopyresampled()" by "imagecopyresized()", as we are not doing any resizing in this line, just cropping. The resizing is already done when this code get executed. Should give slightly better performance? // centercrop defaults: $w1 = ($gdWidth - $targetWidth ) / 2; $h1 = ($gdHeight - $targetHeight) / 2; // read the crop direction from options, hardcoded for testing only: $cropDirection = 'southeast'; switch (strtolower($cropDirection)) { case 'northwest': $w1 = 0; $h1 = 0; break; case 'north': $h1 = 0; break; case 'northeast': $w1 = $gdWidth - $targetWidth; $h1 = 0; break; case 'west': $w1 = 0; break; case 'east': $w1 = $gdWidth - $targetWidth; break; case 'southwest': $w1 = 0; $h1 = $gdHeight - $targetHeight; break; case 'south': $h1 = $gdHeight - $targetHeight; break; case 'southeast': $w1 = $gdWidth - $targetWidth; $h1 = $gdHeight - $targetHeight; break; } imagecopyresized($thumb2, $thumb, 0, 0, $w1, $h1, $targetWidth, $targetHeight, $targetWidth, $targetHeight);
    1 point
  24. Great news, congratulations Ryan and Family!
    1 point
  25. Can anyone tell me more about this? Since it's audio, I don't even have a chance of attempting to translate it. Though from the program summary it sounds like they had some good things to say about PW? I think it's great that people are writing and talking about PW so much this week.
    1 point
  26. Hello bytesource, Yes, I also overlooked this feature when I first started using ProcessWire. But then I found it, and it makes a big difference in adding photos. Like everything else in this system, it's as much as we need without adding more than we need. Thanks, Matthew
    1 point
  27. That's something that we already have, as the comments appear in the page editor for every page. The purpose of this module is to provide all the other possible views. Though it could be said that this interface is better for managing comments in general, so we may eventually make it the standard and keep them out of the page editor. This is in part because the page editor doesn't scale well to situations where you start having hundreds of comments on a page. It'll work, but it's not designed for pagination, whereas the Comments Manager is. So a page-level filter probably will be coming to the Comments Manager.
    1 point
  28. Thank you Exceptionz, I really appreciate your help! We've decided to keep it this way for now, although, if this proves to be a much of an hassle in the future, maybe then, we'll try to contact them again. Thank you very much!
    1 point
  29. I like that idea! I'm studying and sometimes work as freelancer. A Project based on ProcessWire would be fun
    1 point
  30. Hi Mathew, That's how I am doing it right now. What I wanted to ask is if there is a way to just specify a folder instead of uploading every single image one by one. However, I just realized that I can select more than one image at a time, thus turning the once repetitive task of uploading images into a one-time task.
    1 point
  31. New revision of WorkingDraft ist now available (german podcast, covering ProcessWire): http://workingdraft.de/99/
    1 point
  32. Greetings, Any chance of doing a future conference in New York or Boston? I'd definitely help organize it. Thanks, Matthew
    1 point
  33. Great module! Thanks Adam for doing it, great job. 1. I enabled invis and everytime I save the page there's some chars appended in the editor like -> -> -> I use MD textformatter, and have use focus mode on. Not sure what's happening. 3. Also I get some warning when debug mode on in admin: "Notice: Trying to get property of non-object in /xxx/site/modules/InputfieldAceEditor/InputfieldAceEditor.module on line 125 Changing it to "if($field && $field->textformatters)" removes it. 2. Don't know if it's possible anway, but would be maybe nice if the "editor" area would be drag sizable in height like textareas. Keep up the good work.
    1 point
  34. Correct me if I'm wrong, but what Google doesn't like are 302s. 301s aren't themselves bad, but can be less helpful to pagerank when stacked. I don't agree with the broad statements of the linked article. A properly used 301 is in fact a great thing for SEO. But also something to be careful with if you want to maximize the value of it. My experience has been that proper use of 301s is one thing that separates the good SEOs from the unknowing ones. They enable you to relocate URLs in a manner Google will transfer pagerank through. They also enable you to ensure people are always arriving at a consistent URL, thereby making it extremely likely that people will link to you in a consistent manner. Lack of properly used 301s increases the odds of diluted pagerank and duplicate content penalties. When someone loads domain.com in their browser and it 301s to just www.domain.com (or the opposite), thats a good thing. When someone types www.domain.com/about-us in their browser and it 301s to www.domain.com/about-us/, that's a good thing. When you have an old About Us link at domain.com/page.php?id=123 that 301s to www.domain.com/about-us/, that's a good thing. This is all good for SEO and good for the users. If this is consistent and stays that way, the external links that you build up over time will also be consistent. The pagerank that you accumulate over time will be maximized, not diluted. And what rare external links that point to content at an inconsistent URL will be identified as such by Google while still transferring pagerank. Where benefit starts getting lost is when you use 301s in a manner that sends it through several paths. My understanding is that Google does dilute pagerank somewhat the more 301s it has to go through in order to meet a request. Example: link points to domain.com/page.php?id=123, which redirects to www.domain.com/page.php?id=123 which redirects to www.domain.com/about-us which then redirects to www.domain.com/about-us/. The user still gets to the right place (good) but the pagerank value of the link that was pointing to domain.com/page.php?id=123 has been diluted to some extent (though don't know how much). Meaning, lost potential, but certainly better than a 404. A smart SEO keeps tabs on this stuff and corrects the first 301 to redirect to the proper URL rather than having to go through further unnecessary 301s. Pagerank potential gets maximized rather than diluted. The use of a slash vs. non-slash shouldn't be a factor for SEO, so long as it's consistent and 301s to the proper version (excluding root level of course). When someone is advising you to always use trailing slashes, I think this is what they are really saying: 1. Always be consistent in how you link to your own pages (regardless of slash standard). Preventing an unnecessary 301 here reduces the chances of some other 301 getting stacked on top of it. It maximizes the value of the link. 2. Standardizing on a trailing slash reduces the chances of having to implement more 301s later (further reducing the chances of a 301 stack). From an SEO standpoint a trailing slash will scale better because there is no functional reason to ever have to change. Whereas, without a trailing slash there is potential for having to change to one in order to accommodate future growth. I keep up with SEO stuff, but it's not my full time job either, so someone correct me if any of this has changed.
    1 point
  35. Andrew I think you did the right thing by leaning about and implementing this the way you did. It's the sort of thing that really belongs with the site, server and developer rather than the CMS. ProcessWire doesn't make assumptions about where and how you are using it (or if you are even using it for http), so logically we probably shouldn't make assumptions about expires headers apache should send for static files. Though I can see potentially adding some options for setting this stuff with PW-managed output.
    1 point
  36. Great site Diogo! Great design all around. For the videos page, does it grow infinitely (on scroll) or is pagination introduced at a certain limit? I saw it mentioned UT Austin in the footer--that's where my wife went to graduate school.
    1 point
  37. I think this makes sense. I'll look into adding this. I don't know all the technical details surrounding this, and only recently started caring about Retina screens, but maintaining multiple images to target different displays sounds like a short term strategy, not a long term one. At least, I'd have a hard time believing we'd be doing this 5 years from now. I would expect pixel density might keep going up over time. Even if it uses more bandwidth, it seems like the safest strategy for individual images would be to just double the resolution and scale it to 50%. Meaning, if you want to display an image at 300px wide, then make it 600px wide and specify 300px in the width attribute or style. But I'm writing in the context of TinyMCE embedded images and other one-off images. For something like a photo gallery where there are going to be huge differences in bandwidth, or other bandwidth-dependent situations, maybe these browser sniffers and multiple copies of photos make sense… make the people with Retina screens pay for the bandwidth rather than everyone else. Still, doubling the pixel density on images seems to offer some better future proofing and we'll probably all be using this level of density in our displays a few years from now. For the new processwire.com site, I noticed the ProcessWire logo looked crappy on my iPad and iPhone, so saved out a double-size copy, but kept the width/height dimensions the same on the <img> tag. Now it looks great on retina screens, without making any difference on other screens. I think this is the strategy Martijn was referring to for possible inclusion to PW's image placement.
    1 point
  38. I do the same thing that apeisa mentioned. However, I also prefer to keep other things in the site structure where possible, even if I don't intend to use them for front-end views. I often setup template files for these things for my own use (or the client/admin's use), and it can be quite useful. I've found that the approach scales very nicely and enables things to grow over time without becoming more complex. When not practical within the site structure, that's when you use your /tools/ structure. It only becomes messy if you treat pages as buckets, and buckets are messy. If you treat it as structure and put thought into where something should go and why it should go there, what you end up is something extremely organized and purposeful. If something is a non-visual page, does that matter? You see it in an administrative interface, where administration is the purpose. Where I would not want to see the non-visual page is on the front-end. Another thing to consider is whether something should really be "non-visual". I prefer to implement template-files/views for nearly everything on my sites, even things I might consider non-visual in other platforms. The benefits become obvious once you start doing it. However, ProcessWire will happily maintain pages that have no output too. But experiment with implementing output for things you previously thought as non-visual and see where it takes you. It often opens up great new paths to information and is an excellent SEO tool for increasing cross references in your site. For example, consider these pages from the modules directory that started out as non-visual. I went back and implemented an "author" template that does nothing other than show the modules by that author. Yet it's quite useful. This may be an obvious example, but the same concept applies to all kinds of situations. This is only true if you code with a dependency on structure. The suggested route is to select by IDs, templates, relative references or some other field to depend on when you are dealing with potential structure changes. Selecting by path is just one way to pull from other pages, but far from the only way. We use it a lot in examples because it is the easiest to communicate with in the context of examples. But that doesn't mean it's always the right way. Ultimately what is right or what is best just depends on the situation. Using the "hidden" checkbox is a good way to immediately differentiate such pages. However, for something better and more automated, check out mindplay.dk's excellent Template Decorator module. I'm hoping he will add this to the modules directory soon! It is possible, but it's not something I would suggest. I think it's fine to create one-off structures for menus where you might want to vary from the page structure for specific situations like footer links, or even primary navigation in some cases (*see note). But if you build your entire strategy on that, you are adding a load of unnecessary complexity to a site, disconnecting navigation from structure, and ultimately creating a mess that could have been avoided with a little planning. *I think page reference fields, combined with PageListSelectMultiple input are often times a lot better for this stuff.
    1 point
  39. Well, just for fun, these are my rough notes (I have hidden all the ones that say things like "what the bloody hell is this?" or are my notes directly about one of my projects https://sites.google.com/a/stonywebsites.co.uk/cms-notes/
    1 point
  40. Today the german "Webkrauts" published an article by Michael van Laar about PW in their advent calendar: http://webkrauts.de/...012/processwire I think by tomorrow the new revision of a german podcast called "Working Draft" will be published where I talked over 20 minutes about PW. And here it is: http://workingdraft.de/99/ [everything in german, sorry]
    1 point
  41. Hey all! Finished 1.0 version! Updates for version 1.0 [add] Added Textile mode, with huge number of enhancements [add] Added auto mode select (yes!) [add] Added PHP mode, even though there are no means to invoke that yet [enh] Enhanced quote rendering in markdown [enh] Added many styles (sup,sub,cite,code,ins,del,…) [fix] Fixed the default values (and saving the default values) [cng] Show invisibles is off as default Note: Still testing in various browser Please, let me know on github, what works and what doesn't. Thank you!
    1 point
  42. very nice work, excellent. and an interesting project too.
    1 point
  43. Antti, yes, it's certainly possible. You can hook whenever and wherever you like. It's just a matter of being certain your hook has been registered before the event you're aiming for takes place. So you only need an autoload module to hook something you don't have full control yourself, and don't want to or are not able to require some initialization being called before using the hook. Here goes. And this one I tested a little so I know it works, for me at least . function myCustomAuthentication($event) { $user = $event->arguments[0]; $pass = $event->arguments[1]; // TODO: do whatever check is needed to authenticate $user // $pass has whatever you like, a token of some kind probably // must set replace-flag to prevent the original Session::authenticate() being called $event->replace = true; // return value is boolean // true: successfully authenticated // false: authentication failed $event->return = true; } // ...aquire a user name, somewhere, somehow... // hook *before* Session::authenticate() to override it // second argument is null because we're using a plain function and not a method inside an object $session->addHookBefore('authenticate', null, 'myCustomAuthentication'); // log in the user, passing whatever needed by myCustomAuthentication() as a password - if anything $user = $session->login("some-username", "some-token-with-a-meaning-in-this-very-context"); I'll actually be using this piece of code myself as well, this week I hope.
    1 point
  44. Make sure you are logged out too. Pages aren't cached for you when you are logged in. There are other factors that can disable the cache, but most under the template settings. And of course a page is only cached once the cache has been generated, so if you are hitting a bunch of pages for the first time in an hour then it's likely none of them were cached. In general, cache is only used for the 'guest' user. I am working on a so called super cache module that bypasses both MySQL and PHP. It uses the apache rewrite engine to pull cached urls directly from static files.
    1 point
  45. Just experimented also a little and made a little example based on Martjin's code. With some improvements and simpler add image routine. No need to create a new PageImage as the page already has PageImages field. Just add the path to the file and save page. This can also be a remote web url. Also this example shows how error handling can be done. I also used a "/.tmp_upload" folder to upload images first and only add to the page if everything is valid. Since $u->execute() uploads the file to the destination specified, it could be a security issue, if not dealed correctly with it. As far as security goes this folder should be made publicly not accessible via htaccess (in comment). In 2.3 you could maybe use built in restriction to files on pages, but not sure it would be appropriate here. Further, I delete the images uploaded in tmp folder in either case. This is all example code and may even need additional security for real public uploads. (mime types check of files by the WireUpload is sufficient? Ryan?) I've put the code on gist.github: https://gist.github.com/4150974
    1 point
  46. Great tutorial Soma! This is the best summary of using PW's Inputfields that I've seen. I noticed you did $field->attr('id+name', 'email') so just wanted to explain what that is for those that may be unsure of the syntax. That syntax is basically saying to set the 'id' and 'name' attribute to have the 'email'. While every field needs a 'name' attribute (like in HTML) the 'id' attribute is optional… if you don't assign an id attribute, PW will make one up. If you intend to custom style a field with CSS or target it from javascript, then it's best to assign your own 'id' attribute. Otherwise, it doesn't matter. // this… $field->attr('id+name', 'email'); // …is the same as: $field->attr('id', 'email'); $field->attr('name', 'email'); // …as is this (direct reference): $field->id = 'email'; $field->name = 'email'; The advantage of using the attr() function over direct reference is that attr() can't ever collide with other Inputfield properties that might have the same name as a field attribute. It's basically your way of saying "this should definitely be an HTML attribute and not anything else." For recognized attributes like 'name' or 'value' it doesn't matter what syntax you use because an Inputfield already knows 'name' and 'value' are standard HTML attributes. But if you needed to add a custom attribute like "data-something", well then you'd definitely want to use the attr() method of setting. That attr() method should only be used for things that would actually be HTML attributes of the <input>, because they will literally end up there. So if you do an $field->attr('label', 'Hello'); you'll end up with an <input label='Hello'> in the markup, which is obviously not something that you want. That's why you assign a non-attribute property like 'label' or 'description' directly, like: $field->label = 'Something'; Last note about $attr() is that it can be used for both setting and getting attributes: $field->attr('value', 'something'); echo "The field's value is: " . $field->attr('value'); // same as: $field->value = 'something'; echo "The field's value is $field->value"; To extend your example, lets say that you wanted the 'email' and 'password' fields in a fieldset titled "About You". You would create the fieldset, and then add/append the fields to the $fieldset rather than the $form. Then you'd add the $fieldset to the $form: $fieldset = $modules->get('InputfieldFieldset'); $fieldset->label = 'About You'; $field = $modules->get("InputfieldEmail"); $field->label = "E-Mail"; $field->attr('id+name','email'); $field->required = 1; $fieldset->append($field); // append the field $field = $modules->get("InputfieldPassword"); $field->label = "Password"; $field->attr("id+name","pass"); $field->required = 1; $fieldset->append($field); $form->append($fieldset); Or lets say that you wanted those 'email' and 'password' fields to be each in their own column so that are next to each other horizontally rather than vertically. You would assign the 'columnWidth' property to both the email and password fields. In this case, we'd give them both a value of 50 to say that we want them to be a 50% width column: $field->columnWidth = 50; To jump out of tutorial mode and into idea mode: lately I've been thinking that PW should have a YAML to Inputfields conversion tool in the core (something that would be pretty easy to build), so that one could define a form like this: And create it like this (where $yaml is the string above above): $form = $modules->get('InputfieldForm'); $form->load($yaml); echo $form->render();
    1 point
  47. $user = $users->get('antti'); $users->setCurrentUser($user); If you want to make the user persistent for the session (without having to do the above on every request), then do this: $session->_user_id = $user->id;
    1 point
  48. joshuag on a killing spree!
    1 point
  49. Ryan, Thanks this gave me a great place to start. I thought I'd share the version I created in case anyone finds it useful. • Single template for the login/logout. • Automatically redirects the user back to whatever page they originally requested after they login. ./includes/login.php <?php // Handle logouts if($input->get->logout == 1) { $session->logout(); $session->redirect($page->path); } // If they aren't logged in, then show the login form if(!$user->isLoggedin()){ // check for login before outputting markup if($input->post->user && $input->post->pass) { $user = $sanitizer->username($input->post->user); $pass = $input->post->pass; if($session->login($user, $pass)) { // login successful $session->redirect($page->path); } else { $session->login_error = 'Login Failed. Please try again, or use the forgot password link below.'; } } ?> <!DOCTYPE HTML> <html lang="en"> <head> <title>Custom PW Login</title> </head> <body> <form action='./' method='post'> <div class="login"> <? if($input->post->user && $input->post->pass) { echo "<p class='error'>" . $session->login_error . "</p>"; }?> <p><input type='text' id="user" name='user' placeholder='Username'/></p> <p><input type='password' id="pass" name='pass' placeholder="Password" /></p> <p><input type='submit' class="btn" name='submit' value='Login' /></p> </div> </form> </body> </html> <? die(); // don't go any further if not logged in } // end !logged in ?> In any template you wish to protect: <? require("./includes/login.php");?> To trigger a logout: <a href="?logout=1">Logout</a> Note: I'm using the HTML5 placeholder attribute. Browser support is not 100%. You may want to use labels instead, or use some jQuery (like I did) to add the placeholder text for browser that don't support it. SideNote: How do you get code indents to stick when posting? I'm having to go back and add spaces to each line. I use tabs when coding.
    1 point
×
×
  • Create New...