Leaderboard
Popular Content
Showing content with the highest reputation on 01/25/2015 in all areas
-
Not a problem in this case. You would use the template of the parent page, "posts" in this example: Posts post1 post2 post3 The post pages themselves wouldn't need a template, since they wouldn't be shown directly. The only problem I see with this approach is that you wouldn't be able to use the $page->url method for getting this pages, but create your own method to generate the new urls Anyway, I'm not sure that these WP urls are really better than mysite.com/posts/post-name3 points
-
This setup is meant to work with all your site directories in the same folder. Means this should look like below and all three domains (domain1.com, domain2.com. domain3.com) have to point to the same physical location. Here this would be /home/web1/public_html/. For this setup the index.config.php kongondo posted would do the expected job. /home/web1/public_html/ ⌊ site-domain1 ⌊ site-domain2 ⌊ site-domain3 ⌊ wire Maybe your setup would work if you symlink the wire director to all your public_hml folders and all the public_html folders containing the index.php and .htaccess. But I can't tell if the symlinked wire directory would find the site directory.2 points
-
Date archiver automatically archives pages based on a Datetime field (e.g. /news/2013/01/03/some-news-item/).2 points
-
@adrian - I have added an API method, I'm sure it will come in handy. $this->modules->ProcessJumplinks->add(string $source, string $destination, string $start = '', string $end = '') I think that the WP migrator module should check the permalink format being used (%year%/%monthnum%/%postname%/, for example) and convert it to the Jumplinks-equivalent ({year}/{month}/{name}/, in this case).2 points
-
I have been spending some long evenings building PadLoper. It is my personal project to challenge myself as a developer, but also something I believe ProcessWire really misses: a solid eCommerce platform. I am happy to announce, that I am not very far away from public release, so I did create a little teaser site and email list for all of you that are interested: https://www.padloper.pw/ As many of you now, I also have bunch of eCommerce modules called "shop for processwire". Those remain open source modules, but I am not actively maintaining them (like I really haven't since 2012). All the code in PadLoper is new and it's totally build from ground up. If someone wants to maintain or develop shop for processwire further, I am more than happy for that. There will be some open source components coming from PadLoper also: at least payment modules, but I might also open source the shopping cart module. Padloper released 4th October, 2015: https://www.padloper.pw/1 point
-
In the admin we have an option to set a sorting for children using one field only. I have a problem with children getting sorted randomly when using a date field that is the same for multiple children. Usually we would sort by date and by ID or title, but we are only allowed to specify one field at a time. The problem with this is that once you edit one of those children, the sorting is randomly changed (actually everytime you edit a children) That's not really nice and very confusing. I had to use a dirty hook to change the children sorting one parent manually. $this->addHookBefore("ProcessPageList::find", $this, "sortingChildren"); public function sortingChildren(HookEvent $event){ $sel = $event->arguments("selectorString"); $page = $event->arguments("page"); if($page->template == "news-category"){ $event->setArgument("selectorString", $sel . ",sort=-datetime, sort=-id"); } } Maybe there's already a way I don't know or a module? But then I think this should be in core of course and not a module. Thanks.1 point
-
I'm happy to announce that the official ProcessWire Developer Directory has been launched at http://directory.processwire.com It comprises a developer list and a map and is designed to allow anyone developing with ProcessWire to find each other. It also allows potential clients to find developers as well as illustrating how widely ProcessWire is used worldwide. The developer list displays in random order so as not to favour any one developer and is currently quite short, but it should grow nicely as you create your own profiles. The login process is linked to your ProcessWire forum account so the same details you use to login here will allow you to get started. There is a manual approval process as well as some rules so that we can ensure that the directory contains quality content and is free of spam. As a minimum, developers must have 10 posts here on the forums before they can login and post a profile, however after that there are relatively few restrictions - as long as you follow the guidelines on the Profile form and abide by the Terms and Conditions (a condition of submitting a profile) you will be fine. You may notice small icons/badges next to some developers - these are designed to recognise special contributions to the ProcessWire project and are awarded by staff as part of the approval process. Whilst checking each entry's content we cross-check against forum profiles, the modules directory and other sources to determine which badges apply to a developer. There are plans for more features over time which you can be notified about by checking the box at the end of the profile form. I look forward to seeing your profiles soon!1 point
-
I'm not quite sure if this is worth to be a module. But I needed it... This Fieldtype creates a select list (drop down) in relation to another field (you can restrict the list by setting up certain templates and / or pages). Installation: 1. Clone the module and place FieldtypeSelectRelation in your site/modules/ directory. git clone https://github.com/justonestep/processwire-fieldtypeselectrelation.git your/path/site/modules/FieldtypeSelectRelation (or get it from the module page) 2. Login to ProcessWire admin and click Modules. 3. Click "Check for new modules". 4. Click "install" next to the new FieldtypeSelectRelation module. Usage: After installation, you'll have a new "Select" fieldtype that will allow you to define the items you'd like in the drop down depending on another field. Create a new field and assign type SelectRelation Click on the Details tab, there you find different fields to create your select list Field: required, choose another field you created before from which the select list should be populated Repeater: optional, if the field you chose is included in a repeater, select the repeater here Template(s): optional, restrict your result by setting certain template(s) Page(s): optional, restrict your result by setting certain page(s) Unique Values: optional, check this field if you want to avoid duplicate values (If you enable this, the string value will be saved instead of the ID. You will not be able to reference via ID.) Including not only visible pages: optional, include all hidden and unpublished pages and pages that user doesn't have access to view Multiple Output: optional, multiple selection (using ASMSelect) Unique Values Disabled If this field is not enabled the key is the pages_id and the value is the value from the other field. <select id="Inputfield_chosen_fruit" name="chosen_fruit"> <option value=""></option> <option selected="selected" value="1026">Strawberry</option> <option value="1030">Apple</option> <option value="1031">Banana</option> <option value="1032">Lemon</option> </select> Note: If you change the value of a field the value changes too. If you deleted a value the value now is empty and multilingualism works like a charm. Accessing the value: // single select echo $pages->get((int)$page->chosen_color)->color; // multiple select foreach ($page->chosen_color as $p) { echo $pages->get((int)$p)->color; } `chosen_fruit` and `chosen_color` are of the type SelectRelation. `title` is the page title and `color` a simple input field (TextLanguage for example). In `chosen_fruit` the selected field is `title`. And in `chosen_color` the selected field is `color`. Unique Values Enabled If this field is checked the key as well as the value are the value from the other field. <select id="Inputfield_chosen_color" name="chosen_color"> <option value=""></option> <option value="red">red</option> <option value="green">green</option> <option selected="selected" value="yellow">yellow</option> </select> If you don't check this box you might have duplicate colors (because there is more than one fruit which has a yellow color for example). BUT if you change the value of an field, your already chosen value stays the same, because there isn't a relation via ID. Access such a field like you are used to: // single select echo reset($page->chosen_color); // multiple select foreach ($page->chosen_color as $p) { echo $p; } TL;DR: I tried to save a comma separated list for duplicate values .It works until you change anything. For example, if you have two times the color yellow a key of the kind '1034,1036' may get saved. Now assume you change a basic color (the banana turns brown ), the selected value is now empty because a key like '1034,1036' doesn't exist anymore. And in the frontend you may get a wrong output.1 point
-
since everyone is trying to make themes based on their own wishes and needs, I tried to have a view from our clients: what do they really need? how often? what should they see and what not...? so I ended up with a really clean theme. the trash page will not be shown in the page tree. I'll move it in the right bottom corner. some footer informations are not necessary to be visible all the time (eg. pw version, copyright). I want to hide them behind a button. I often see people looking for a "back button" because they don't want to use the browser back button (don't know why - maybe just my view?). some ideas for other features (like custom colors)? let me know what you think. thanks1 point
-
It is just a HTML5 placeholder attribute. It just shows text in a field until the field is focused. See it as a helper for editors (who are smart enough to use a modern browser) For the PHP part, an if statement like this will work. if ($page->price) { echo $page->price; } else { echo 'Please ask....'; }1 point
-
It's also easy to create a hook that creates folder automaticLy and put post there or move it if date changes.1 point
-
It's all on the field's settings. Go through them and you'll find it.1 point
-
For dates I would suggest adding a date/time field to your template. Call it "post_date" for example. Have it default to today's date. That way you don't have to set it, but you can adjust it if needed. This lets you pre/post date your entries easily. Now instead of using "created" in your selector, use the name of your new date/time field "post_date".1 point
-
Hello, I've used this module and I obtain this error too: Error: Exception: Method TemplateFile::entityEncode does not exist or is not callable in this context (in /www/htdocs/staeding/processwire/wire/core/Wire.php line 320) If your are using the demo files as they were, there is an error on the file includes/contact-form.php Around the line 62, the follow line: echo $this->entityEncode($error, true); Must be: echo $field->entityEncode($error, true); The Method entityEncode belongs to the class InfputField an not to the class Template. It worked in PW 2.5.2. I hope it can be useful to someone. Best regards.1 point
-
Perhaps this could point you in the right direction? What version of PHP/MySQL are you running?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
-
I just came across with this topic and wanted to share my experience. The problem with permissions is simple: The Apache user (see: PHP) has no permission on files we upload with our FTP user and the same goes the other way around too. On shared hosting the solution for us was to change PHP to run as fastCGI instead of as Apache module. This way you can upload files via FTP, leave permissions as the recommended 755 and 644 and php will be able to happily write those files/folders. Also, you can edit/delete files and folders via FTP even though they were created by PHP. On my VPS running Webmin I just make sure that I upload files with the virtual host user and not with the root user. I hope it helps to sort the cause of the problem and not just treating the symptom.1 point
-
You won't find anything specific to Blog. I suggest you search the forums at large for something like this: 'limit page editing to the user that created that page' https://processwire.com/talk/topic/3271-can-i-limit-page-editing-to-the-user-that-created-that-page/ Read that whole thread and modify the autoload module to suit your needs.1 point
-
The first (maybe naive) structure that come my ming is as seen on the screenshot below You may also want to look at the blog module here.1 point
-
1 point
-
Got it! I found the Permissions class which is also based on PagesType and was able to find its instantiation in ProcessWire.php, which was helpful. I had to add the following to the init() method in my module: $customers = new Customers($this->templates->get('si-customers'), $this->pages->get("template=si-customers")); // Instantiates the Customers class $this->wire('customers', $customers); // Make the $customers variable available to templates My Customers class right now is just: <?php class Customers extends PagesType {} And is then required at the top of my module.1 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
-
<ul> <?php foreach($homepage->children as $nav){ echo "<li>".$nav->title; if($nav->numChildren){ foreach($nav->children as $nav_2){ echo "<li>".$nav_2->title; } } } ?> </ul> This should generate a single list of entries, even though pages are nested in the backend. Just change the variables to fit your purposes.1 point
-
Thanks! It would be great to have a link of the developer page to the forums member page and if the developer created some modules the reference as well. (And I miss my module author icon )1 point
-
Hello @Philipp First of all, thank you for this great service! Trying it out today as a demo platform for a new module I'm getting close to releasing. I'm having some trouble logging in using ftp. I'm pretty sure the credentials I'm using are correct but I keep getting '530 Login Incorrect' errors when I try connecting using gFTP. Are there some limitations on the daemon's ability to accept non-ascii characters in passwords? Login with the same password to the admin interface is just fine. Thanks in advance!1 point
-
coming back to this: I have made good progress! I do not use the htaccess file in site/assets/files/ anymore but have edited the htaccess file in pw root folder. Somewhere at top of the mod_rewrite directives I have added my lines that should redirect requests to original images to a proxy-script and let others pass through: htaccess with Pim1 and PW < 2.5.11 .htaccess with PW 2.5.11+ / PW 3+ # ----------------------------------------------------------------------------------------------- # CUSTOMSETTING : redirect original images to proxy-script - /pwimg.php?fn=... # ----------------------------------------------------------------------------------------------- RewriteCond %{REQUEST_FILENAME} -f RewriteCond %{REQUEST_FILENAME} (^|/)site/assets/files/(.*?)/ RewriteCond %{REQUEST_FILENAME} \.(jpg|jpeg|gif|png)$ [NC] RewriteCond %{REQUEST_FILENAME} !-piacrop RewriteCond %{REQUEST_FILENAME} !-piacontain RewriteCond %{REQUEST_FILENAME} !-pim2-full RewriteCond %{REQUEST_FILENAME} !-blogthumb RewriteCond %{REQUEST_FILENAME} !.*/.*?\.([0-9]+)x([0-9]+)\.(jpg|png|jpeg|gif)$ [NC] RewriteRule ^(.*)$ pwimg.php?fn=$1 [L] Now from all existing images the originals get redirected to the proxy-script and the others will delivered directly by apache. Requests to none existing imagefiles get answered by a 404. So as everything seems to work fine, the RewriteConditions could be optimized a bit. ---- pwimg.php ---- <?php // check filename $imgFilename = isset($_GET['fn']) ? preg_replace('/[^a-zA-Z0-9_\-\/\.@]/', '', $_GET['fn']) : false; $imgFilename = is_file(dirname(__FILE__) . "/$imgFilename") && is_readable(dirname(__FILE__) . "/$imgFilename") ? dirname(__FILE__) . "/$imgFilename" : false; if (false == $imgFilename) { header('HTTP/1.1 404 Not Found'); exit(2); } // check imagetype $imgType = getImageType($imgFilename); if (false == $imgType) { header('HTTP/1.1 403 Forbidden'); header('Content-type: image/jpeg'); exit(1); } // bootstrap PW require_once(dirname(__FILE__) . '/index.php'); // check user-account if (! wire('user')->hasRole('superuser|editor')) { header('HTTP/1.1 403 Forbidden'); header('Content-type: ' . $imgType); exit(1); } // collect infos $maxAge = (60 * 60 * 2); // 2 hours $imgTimestamp = filemtime($imgFilename); $imgExpiration = intval(time() + $maxAge); // create headers $imgHeaders = array(); $imgHeaders[] = 'Content-type: ' . $imgType; $imgHeaders[] = 'Content-Length: ' . filesize($imgFilename); $imgHeaders[] = 'Date: ' . gmdate('D, d M Y H:i:s',time()) . ' GMT'; $imgHeaders[] = 'Last-Modified: ' . gmdate('D, d M Y H:i:s',$imgTimestamp) . ' GMT'; $imgHeaders[] = 'Expires: ' . gmdate('D, d M Y H:i:s', $imgExpiration) . ' GMT'; $imgHeaders[] = 'pragma: cache'; $imgHeaders[] = "Cache-Control: no-transform, private, s-maxage={$maxAge}, max-age={$maxAge}"; // send headers foreach($imgHeaders as $imgHeader) header($imgHeader); // send file $errorCode = @readfile($imgFilename) === FALSE ? 1 : 0; // and exit exit($errorCode); // --- functions --- function getImageType($fn, $returnAsInteger = false) { $types1 = array(1 => 'gif', 2 => 'jpg', 3 => 'png'); $types2 = array('gif' => 1, 'jpg' => 2, 'jpeg' => 2, 'png' => 3); if (function_exists('exif_imagetype') && isset($types1[@exif_imagetype($fn)])) { $success = $types1[exif_imagetype($fn)]; } if (!isset($success) && function_exists('getimagesize')) { $info = @getimagesize($fn); if (isset($info[2]) && isset($types1[$info[2]])) { $success = $types1[$info[2]]; } } if (!isset($success)) { $extension = strtolower(pathinfo($fn, PATHINFO_EXTENSION)); if (isset($types2[$extension])) { $success = $types1[$types2[$extension]]; } } if (!isset($success)) return false; return true === $returnAsInteger ? $types2[$success] : $success; }1 point