Leaderboard
Popular Content
Showing content with the highest reputation on 01/26/2015 in all areas
-
This is a recently launched project, proudly powered by Processwire. https://www.bethfalk.com/ Mini Case Study: ...the site was meant to be a quick, simple job, but did get 'interesting' after it started.. The client chose the 'Centum' template, something of a classic by Vasterad (also aval. as a wordpress and drupal theme) but the template had some technical problems and a lot of things were fixed/improved/re-coded. I think this is a great 'theme' for this sort of site.. it's clean and had enough functionality built in to make my job a bit simpler... I'm using the following modules: Admin Custom Files Admin Custom Pages AIOM+ Email Obfuscation Fieldtype DataStructure Profields Table Formbuilder Procache Form Save Reminder Hanna Code (for tabs and accordions) Hanna Code Helper Process Diagnostics Page Lister Pro Site Utilities (custom module, used for populating default slide settings in a table, for homepage slider).. BBCode These topics all relate to functionality that was developed for this project (and some other projects all bundled together during the last 4 months): https://processwire.com/talk/topic/8373-use-delimited-texarea-table-or-yaml-for-settings/#entry81202 https://processwire.com/talk/topic/8635-simple-example-for-widget-management/#entry84623 https://processwire.com/talk/topic/8392-simple-built-in-docs/#entry82915 Other related topics: https://processwire.com/talk/topic/8350-module-fieldtype-yaml/?p=80908 Where possible I tried to use some schema.org microformats; to be continued..9 points
-
What happens when the user disblaes JavaScript ?, I do it on several site (only when my evil side wakes up). Never Trust user input and frontend security mechanism. That being said truly this is where frameworks have an advantage however you can use Valitron and PW Form together, I used Valitron alot and its the one Validation lib that doesn't suck after Yii and Zend 2, all you need to do is create the rules and validate the rules against the values from the form and all is good to go.3 points
-
Full working code I used following lipsum php generator https://github.com/alexscottmoore/Lorem-PHPsum <?php include "lorem-phpsum.php"; include('index.php'); $startdate = "2013-01-01"; $enddate = date("Y-m-d H:i:s"); echo "Generate dummy blog post"; for ($i=1;$i<=30;$i++) { $blog = wire('pages')->get('/blog'); $p = new Page(); $p->template = 'post'; $p->parent = $blog; $p->title = phpsum(5); $p->body = phpsum(10, 20, 3); $p->post_date = randomDate($startdate, $enddate); $p->of(false); echo "Saving post...."; foreach($wire->languages as $lang) { if($lang->isDefault()) continue; $p->set("status$lang", 1); $p->save(); } } function randomDate($start_date, $end_date) { // Convert to timetamps $min = strtotime($start_date); $max = strtotime($end_date); // Generate random number using above bounds $val = rand($min, $max); // Convert back to desired date format return date('Y-m-d H:i:s', $val); } ?>3 points
-
@pwired - so far i have never had to solicit clients.. so far riding the referral chain!2 points
-
Hey Macrura - nice looking site! One minor thing - the navigation-divider.png looks a little weird to the right on the selected menu item. If I disable it, that little black line goes away and looks better. I understand it looks good between the unselected items, but it does look weird to the right of a selected one which is green. #navigation ul li a { display: inline-block; color: #fff; text-decoration: none; font-size: 13px; font-weight: 500; padding: 17px 25px; background: url(/site/templates/centum/images/navigation-divider.png) no-repeat right 50%;2 points
-
Just to add to the client-side/server-side thing: Since my first PW site, I've created a simple module (only for contact forms) that makes use of SwiftMailer (I should probably be using wireMail, but I haven't even looked at that yet) and Laravel's Validation package. The form itself works with JavaScript, but validation occurs on the server-side. All well and good, that's good practice. But I specifically ensure that the form doesn't work when JS is not available. Just my 2cents on the matter.2 points
-
There is also this lorem ipsum module for PW: http://modules.processwire.com/modules/markup-loren-ipsum/2 points
-
If it's only about the knowledge, there are more people besides Ryan here on the forums, which have the ability to build such modules. The thing is, there has to be a big enough market to sell something like this to. But maybe this topic can act as a display for the need of such a module in the community.2 points
-
You can always use client side validation, but server side is a must. You can't rely on validated data being sent to your server, as everyone how can read your form can potentially send whichever data he wants to your server. Even if it's not a security risk per se, would you want users to be able to save a 10 star rating on the server side, when there should be a maximum of 5 stars possible.2 points
-
Hi Nico, Thanks for this module! Love it much I think I may have found a conflicting issue when this module is installed along side with ProcessBackup (DB Backup module). There is an error when you try to view the Database Backup detail and I believe it may be caused by the following line: $editedPage = wire('pages')->get($this->config->input->get->id); The SEO module kicks in when trying to view the database backup page because there is a querystring id in the url. setup/db-backups/info/?id=0:dev.cc26012015-01.sql The fix is pretty simple: public function ready() { // backend hooks if(@$this->page->process == 'ProcessPageEdit') { $editedPage = wire('pages')->get($this->config->input->get->id); if(in_array($editedPage->template->name, $this->includeTemplates)) { $this->addHookAfter("ProcessPageEdit::buildFormContent", $this, 'hookCustomizeSeoTab'); } } // frontend hooks if($this->page->template != 'admin' && in_array($this->page->template->name, $this->includeTemplates)) { $this->addHookProperty("Page::seo", $this, 'hookFrontendPage'); $this->addHookProperty("Config::seo", $this, 'hookFrontendConfig'); } } Check the ProcessEditPage first before look for the edited page object. But anyway, I thought I let you know Thanks much again!2 points
-
MarkupSocialShareButtons This module outputs a list of share links for the following services by default * E-Mail (kinda extra) * Facebook * Twitter * Google+ * LinkedIn * Thumblr * Reddit (off by default) * Pinterest (off by default) Usage examples echo $modules->MarkupSocialShareButtons->render(); This outputs a simple UL list with links <ul class='MarkupSocialShareButtons cf'> <li class='mssb-item mssb-facebook mssb-popup'><a href='url'><i>facebook</i></a></li> etc ... </ul> Config Screen See more details and examples on github or modules directory https://github.com/somatonic/MarkupSocialShareButtons http://mods.pw/8j1 point
-
I don't normally like wysiwyg web editors or any other similar tools out there but I stumbled upon Pinegrow and I have to say wow. It is useful in so many ways. Description from Pinegrows: 'a desktop app that lets you build responsive websites faster with live multi-page editing, CSS styling and smart components for Bootstrap, Foundation, AngularJS and other frameworks.' Check out the video below for a quick introductory look at it: Just wanted to share this with anyone that thinks this can help their workflow.1 point
-
It looks like LinkedIn use OAuth for this process, just like Facebook and Twitter and GitHub. There are ProcessWire modules that handle those networks: Facebook (in modules directory) Twitter (my module: Thread, GitHub) GitHub (Repo) I would start by looking at those, learning how they work, and then building one for LinkedIn that meets your needs1 point
-
Update: Blog version 2.3.2 Additions Thanks to idea by @justb3a, I have added a new method renderRelatedPosts() to MarkupBlog. The method returns a PageArray of posts related to the post currently being viewed or the specified blog post/page. (if related posts found, otherwise returns null). It takes four arguments as follows: renderRelatedPosts(Page $post = null, $relatedBy = null, $limit = null, $sort = null) 1. $post: The post whose related posts will be returned. Defaults to the current page if none specified. 2. $relatedBy: This sets the criterion for determining how other posts are related to the current post. There are 3 possible options here: a. $relatedBy = 1: posts are related by both tags AND category. This means that in order to be considered as related to the specified post, the posts to be returned must have at least one tag and at least one category in common with the specified post. This is the default relation criterion. b. $relatedBy = 2: posts are related by tags ONLY. Means that at least one tag has to match the specified post's tags. c. $relatedBy = 3: posts are related by categories ONLY. Means that at least one category has to match the specified post's categories. 3. $limit: Number of related posts to retrieve. Defaults to 3 posts. 4. $sort: This determines the related posts to prioritise in the find. It is especially useful when you set a $limit. It defaults to sort by blog_date DESC, meaning latest posts. You can use any other valid ProcessWire sort value, e.g. sort by title, sort by 'most commented on posts' [see example below], sort by random, etc. The method returns no markup and its output can be used in a variety of ways. Examples #RELATED POSTS ##1. used in conjuction with MarkupBlog's renderNav() ##similar to 'Related Categories' in the left-hand navigation in demo Blog 'blog-post.php' template file //CALL THE MODULE - MarkupBlog $blog = $modules->get("MarkupBlog"); //use defaults. Related posts limited to 3, related to this post by BOTH tags AND categories, ordered by blog_date DESC $related = $blog->renderNav(__('Related Posts'), $blog->renderRelatedPosts()); //use renderNav() markup echo $related; //find the 'most commented on' posts related to this post by category $related = $blog->renderNav(__('Related Posts'), $blog->renderRelatedPosts(null, $relatedBy=3, null, '-blog_comments.count')); //find 7 posts, ordered Alphabetically by title, related to this post by tag $related = $blog->renderNav(__('Related Posts'), $blog->renderRelatedPosts(null, $relatedBy=2, $limit=7, 'title')); ##2. used outside blog-post.php or even outside Blog pages $post = $pages->get(2550); //find 5 random posts related to the specified post by BOTH tags AND categories $related = $blog->renderNav(__('Related Articles'), $blog->renderRelatedPosts($post, null, $limit=5, 'random')); //find the 3 'least commented on' posts related to the specified post by tags $related = $blog->renderRelatedPosts($post, $relatedBy=2, null, 'blog_comments.count'); //find 3 posts related to the specified post by tags AND categories $related = $blog->renderRelatedPosts($post); //use custom markup foreach($related as $r) echo $r->title . '<br>'; Screenshot Currently in dev branch only for testing.1 point
-
I think you can do this with the PIM module https://processwire.com/talk/topic/4264-release-page-image-manipulator/ The method you are looking for is canvas() Having said that, I would probably do it with css if it is ok for you using a css background-image instead of a normal <img/>. You can position and scale background-images easily with css like this: <style> .slide { background-position: 50% 50%; background-size: contain; background-repeat: no-repeat; } </style> <div class="slides"> <div class="slide" style="background-image: url(img.jpg)">Content Slide 1</div> <div class="slide" style="background-image: url(img.jpg)">Content Slide 2</div> </div>1 point
-
Hi doolin, and welcome! <?php $fullpictures = ""; ?> <div id="gallery"> <ul id="navigation"> <?php foreach($page->bild as $image) { $thumbnail = $image->size(150,100); echo "<li><a href='#{$thumbnail->description}'><img src='{$thumbnail->url}' alt='{$thumbnail->description}' ></a></li>"; $fullpictures .= "<div><a name='{$thumbnail->description}'><img src='{$image->url}' alt='{$thumbnail->description}' ></a></div>"; } ?> </ul> <div id="full-picture"> <?php echo $fullpictures; ?> </div> </div> Written in browser, so I hope it works, and you can follow what I've done. Essentially, I've taken the example code from the article you were following, and replaced bits with php. The main difference is, so that I only need one loop, is build the content for the 'full-picture' div (in $fullpictures) at the same time as outputting the thumbnails markup, then echo it later within the html markup. See if it works...1 point
-
You could use a autoload module like this https://processwire-recipes.com/recipes/extending-page-save-process/ and use it to change the order of the images on page save. This way you client still has to hit save, but at least it's not manual work. $page->images = $page->images->sort('name'); The other option would be hooking into ProcessPageEdit and adding a javascript file which does the sorting right away.1 point
-
@Mike Anthony: you used SwiftMailer with a contactform? Than this is for you: modules/wire-mail-swift-mailer1 point
-
Wow kongondo, I was out of town and read the response notification on email, but just now saw your diagram in your reply. The fact that you broke this down and described it like you did speaks volumes of your character. This diagram should be added to the docs its so descriptive and informative. Thank you very much for taking the time to explain.1 point
-
Great module, how ever it bugs with Reno theme, requires following: .colorpicker input { background-color: transparent !important; border: 1px solid transparent !important; color: #898989 !important; padding: 0 !important; } Because (/wire/modules/AdminTheme/AdminThemeReno/styles/classic.css): input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]), textarea { background: none repeat scroll 0 0 #eaf0f2; border-color: #aec5cd #c7d7dd #c7d7dd; border-style: solid; border-width: 1px; color: #2f4248; line-height: 1.3em; padding: 0.4em; } So either Reno could strict it's styling rules, or module should add !importants, i'd go with first one Cheers1 point
-
One possibility is to hook ProcessPageEdit::buildForm and build your wanted values from there. So no need for special fieldtype & Inputfield because it looks like overkill to me. Ps, the code here is not tested and written in the browser, it's more to give you an idea. <?php public function init() { $this->addHookAfter('ProcessPageEdit::buildForm', $this, 'afterPageEditBuildForm'); } public function afterPageEditBuildForm(HookEvent $event) { $form = $event->return; $page = $event->object->getPage(); $wantend_template = 'your-template'; // make this your template if (!$page->id) return; // return if wrong template $template = $page->template; $string = 'invoice_'; // for building your field value if ($template->name !== $wantend_template) return; // Skip if not wanted template $fieldnames = array( 'invoice_date', // Field named invoice_date 'customer', // Field named customer 'follow_up', // integer field. ); foreach ($fieldnames as $fieldname) { // Inputfield $obj = $form->getChildByName($fieldname); // Build field value if ($obj->type == 'FieldtypeDatetime') { $string .= strtotime('Y-m-d', $obj->value); } else if ($obj->type == 'FieldtypeInteger') { /** * Make some logic to find the follow_up number field value * */ $integer = '123456789'; // calculate it here $obj = $form->getChildByName($fieldname); if ($obj->value != $integer) { $obj->value = $integer; $obj->resetTrackChanges(); $obj->trackChange('value'); } $string .= $integer; } else if ($obj->type == 'FieldtypePage') { $string .= $obj->value->name; } } // We use the title for your invoice value $InputfieldTitle = $form->getChildByName('title'); $value = $InputfieldTitle->value; if ($string !== $value) { $InputfieldTitle->resetTrackChanges(); $InputfieldTitle->trackChange('value'); $InputfieldTitle->value = $string; } }1 point
-
Sounds good! In my installation I deactivated comments, that's why I havn't though about the option 'most commented on related posts' (but I really like the sort option). I have not that much blog posts so I need the following combination: find related posts by 'both tag AND category', by 'category' and by 'tag' (in that order) to fill my list.1 point
-
Regarding "Related Posts", I have been able to implement this using one line of code , OK, not quite but I have chosen a different route from the previously suggested code. Thanks for the inspiration and ideas though! I will wrap this in a new renderRelatedPosts() method in MarkupBlog. In case you are wondering, the most important line of code is this: $related = $pages->find("template=blog-post, blog_categories=$page->blog_categories, blog_tags=$page->blog_tags, id!=$page->id, limit=3, sort=-blog_date"); I'll post details later but I will make this configurable in the new method, i.e. add options to find related posts by 'tag' OR by 'category' OR 'by both tag AND category'. There will also be an option for limit as well as sort, i.e. if limiting, e.g. to 3 related posts, what's the criteria for your '3 most important related posts'? The default will be 'most commented on related posts' sort by latest posts (blog_date). Then, similar to the 'Related Categories', 'Related Tags' and 'See also' output that you can see in the demo Blog template files running on the left hand side navigation, one will simply need to use the method renderNav() to display Related Posts as follows in the template file 'blog-post.php': $subNav .= $blog->renderNav(__('Related Posts'), $related); Just wanted to post these ideas before I finalise the code in case there is something I am missing? Thanks.1 point
-
diogo is talking about symlinks. Have a look here http://en.wikipedia.org/wiki/Symbolic_link or try google. This way your filesystem can pretend that the wire directory is in fact in all three places, while in fact it's only in one place.1 point
-
1 point
-
You can't assign the parent like that - you need to provide a page object - something like: $p->parent = $pages->get("/blog/"); You should also get into the habit of setting outputformatting off before saving a page: $p->of(false); Correction - even though the above approach works just fine, apeisa's way of assigning the path to the page also works, so my comment about needing a page object is actually not correct!1 point
-
if $page->hotelisim is a Multiple page field, then use count() instead (because it returns an array).. if(count($page->hotelisim)) { //do your foreach stuff here } else { echo 'Please ask'; }1 point
-
Thanks for u repply; the link give me the idea to downgrade my php version to 5.3 and works like a charm. Really Thanks. Regards.-1 point
-
Just approved your entry Felix. Manaus, you should have a private message on the forums with instructions.1 point
-
You would use url segments on your home page. Then from the segments, build a query using $pages->get("selectors") to return a page from this. You'd probably want to use /2015/01/05/ to select the page by date using the "created" field, and page-title-name to select the page by the "name" field, which is used for urls. It would probably look something like that (note that I didn't test this): $year = $urlSegment1; $month = $urlSegment2; $day = $urlSegment3; $name = $urlSegment4; # Assuming your blog posts use a template called "post"... # You need to do >= and < on created because it's using timestamps, # so you're looking for something in a range $page = $pages->get("template=post, created>={$year}-{$month}-{$day}, created<{$year}-{$month}-{$day+1}, name={$name}"); if(!page) { // redirect to 404 or another page or do something else } . . . I personally wouldn't use a directory structure for this, it just makes moving things harder. In WP, these folders don't really exist really either. Also note that you could probably just skip checking the creation date, since page names (url, not to be confused with the title field) are already unique by default. But you might want it anyway for some reason.1 point
-
@mike: Thanks for adding it. I'll take a look. @ceberlin: Select a custom field with a fallback to title? You can use multiple smart titles. So the first one will be used if filled (https://github.com/NicoKnoll/MarkupSEO/blob/master/MarkupSEO.module#L182-L187). If not the second one is used and so on. "Smart title" will be used in case you leave the "Title" field in the SEO tab empty. Canonical Yes it's $page->httpUrl by default (https://github.com/NicoKnoll/MarkupSEO/blob/master/MarkupSEO.module#L233). But you're right. I should add a comment. URL Segments I'm not sure either how to handle them. But as they are not "real" pages I guess this module isn't able to handle them anyway (you can't add SEO fields to non existing pages...) link rel="alternate" hreflang I'll add an option to include this1 point
-
@LostKobrakai, Here's a couple of links on indexing... http://www.sitepoint.com/optimizing-mysql-application/ http://codesamplez.com/database/mysql-indexing-tips http://weblogs.sqlteam.com/jeffs/archive/2007/08/23/composite_primary_keys.aspx http://www.percona.com/files/presentations/WEBINAR-MySQL-Indexing-Best-Practices.pdf http://stackoverflow.com/questions/14206868/two-column-as-a-primary-keys-in-mysql http://stackoverflow.com/questions/217945/can-i-have-multiple-primary-keys-in-a-single-table http://stackoverflow.com/questions/5835978/how-to-properly-create-composite-primary-keys-mysql http://stackoverflow.com/questions/1823685/when-should-i-use-a-composite-index http://stackoverflow.com/questions/5446124/mysql-why-not-index-every-field1 point
-
Great Module! Thanks! I miss one litte functionality - display related posts (or did I miss something?). Maybe someone else needs this, so here is the code (I use this in a TemplateDataProvider): public function populate() { $limit = 3; $selector = array( 'template' => 'template=blog-post', 'id' => 'id!=' . $this->post->id, 'categories' => 'blog_categories=' . $this->post->blog_categories, 'tags' => 'blog_tags=' . $this->post->blog_tags ); // find posts same tag AND category $related = wire('pages')->find(implode(', ', $selector)); if ($related->getTotal() < $limit) { // find posts same category $related = $this->getRelated($related, $selector, 'tags'); if ($related->getTotal() < $limit) { // find posts same tag $related = $this->getRelated($related, $selector, 'categories'); } } $this->related = $related; } private function getRelated($related, $selector, $remove) { $selector['id'] .= '|' . (string)$related; unset($selector[$remove]); $rel = wire('pages')->find(implode(', ', $selector)); return $related->import($rel); }1 point
-
I see two Teppos there ps: by the way, Eelke, I quite like your small yellow / Gill sans site1 point
-
@kongondo What a post. Seemingly crowed by arrows, but after a few looks so full of info. Are there any good tutorials out there about this topic? A few month ago I had my problems to enable fulltext search in one of my modules and I would like to know a little more about this. Preferably without learning SQL in it's entirety.1 point
-
1 point
-
I've added a barebone module to the processwire recipes site, so maybe people will just point to a single source for something like this and Soma doesn't have to ramble about details as much https://processwire-recipes.com/recipes/extending-page-save-process/1 point
-
New year, new site online http://schutzbelueftung.de/ This time industry client, they build ventilation systems for diggers, earth movers and stuff like that. Pretty interesting. English version is in the works, should be ready by march. This is the second page featering my pagetable extended module, with which the client can easily build an individual layout out of predefined layout elements. That means: Everything on the site is filled by the client, all images and text. One special thing is the database of their installations: http://schutzbelueftung.de/aufbaubeispiele/ Here you can filter by company, type field of application. This is done by ajax in the background, so easy to build with the PW selectors <31 point
-
[quotamos]This is really interesting stuff and I'm learning so much from it. I've already tested Soma's code and it works very well. Is there a way of configuring $form->render() so that it outputs different html (divs for ul/li etc.)? [/quotamos] you.can usage. $form->setMarkup(); und $form->setClasses(); two.set markups und html caresses. see.eliamos /wire/core/InputfieldWrapper.php1 point
-
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