Leaderboard
Popular Content
Showing content with the highest reputation on 07/12/2013 in all areas
-
Not specific to multi-language page names, but since it's in the dev branch and related, I figured I'd mention it here… Multi-language page fields inherit the default language value when they are blank. While probably a good default, sometimes this behavior is not desirable. So on the latest dev commit, you can now configure that behavior on a field-by-field basis (for any multi-language field). The screenshot below probably explains it best.4 points
-
For authors, there were only about 6 of them at import time, so I created the authors as users in PW manually. I also added the "wpid" field to the "user" template, and populated the value of that manually. That was easy to find in WordPress just by editing the author and noting the ID in the URL. The WordPress wp_posts table has a field in it called post_author, which is the ID of the author. So assuming we've got a user in ProcessWire with a "wpid" that matches up to that, it's easy for us to assign the right PW user to each post. You'll see how this takes place in the code below. Wrapping it up Here is the same "import" code as in the first post, but I added all the code accounting for authors, topics, tags, and images back into it. This all just goes in a ProcessWire template file, and viewing the page triggers the import. Because it's aware of stuff that is already imported, it can be run multiple times without causing duplication. <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Import Posts</title> </head> <body> <table border='1' width='100%'> <thead> <tr> <th>New?</th> <th>ID</th> <th>Author</th> <th>Date</th> <th>Name</th> <th>Title</th> <th>Images</th> <th>Topics</th> <th>Changes</th> </tr> </thead> <tbody> <?php // get access to WordPress wpautop() function include("/path/to/wordpress/wp-includes/formatting.php"); $wpdb = new PDO("mysql:dbname=wp_cmscritic;host=localhost", "user", "pass", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'")); $posts = wire('pages')->get('/posts/'); $sql = " SELECT * FROM wp_posts WHERE post_type='post' AND post_status='publish' ORDER BY post_date "; $query = $wpdb->prepare($sql); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { $post = $posts->child("wpid=$row[ID]"); // do we already have this post? if(!$post->id) { // create a new post $post = new Page(); $post->template = 'post'; $post->parent = $posts; echo "Creating new post...\n"; } $post->of(false); $post->name = wire('sanitizer')->pageName($row['post_name']); $post->title = $row['post_title']; $post->date = $row['post_date']; $post->summary = $row['post_excerpt']; $post->wpid = $row['ID']; // find the post author $author = wire('users')->get("wpid=$row[post_author]"); // if we don't have this post author, assign one (Mike) if(!$author->id) $author = wire('users')->get("mike"); // set the post author back to the page $post->createdUser = $author; // assign the bodycopy after adding <p> tags // the wpautop() function is from WordPress /wp-includes/wp-formatting.php $post->body = wpautop($row['post_content']); // give detailed report about this post echo "<tr>" . "<td>" . ($post->id ? "No" : "Yes") . "</td>" . "<td>$row[ID]</td>" . "<td>$row[post_author]</td>" . "<td>$row[post_date]</td>" . "<td>$row[post_name]</td>" . "<td>$row[post_title]</td>" . "<td>" . importImages($post) . "</td>" . "<td>" . importTopicsAndTags($wpdb, $post) . "</td>" . "<td>" . implode('<br>', $post->getChanges()) . "</td>" . "</tr>"; $post->save(); } function importTopicsAndTags(PDO $wpdb, Page $page) { // see implementation in previous post } function importImages(Page $page) { // see implementation in previous post } ?> </tbody> </table> </body> </html>3 points
-
Topics and tags: The first step was to create the parent pages and templates for these. For topics, there were only a few of them, so I created all the category pages ahead of time. On the other hand, with tags, there are 2000+ of those, so those are imported separately. Here are the manual steps that I performed in the PW admin before importing topics and tags: Created template "topics" and page /topics/ that uses this template. Created template "topic" and 6 topic pages that use it, like /topics/cms-reviews/ for example. Created Page reference field "topics" with asmSelect input, set to use parent /topics/ and template "topic". Created template "tags" and page /tag/ that uses this template. Note that I used /tag/ as the URL rather than /tags/ for consistency with the old WordPress URLs. Otherwise I would prefer /tags/ as the URL for consistency with the template name. Created template "tag". Created Page reference field "tags" with PageAutocomplete input, set to use parent /tag/ and template "tag". I also set this one to allow creating of new pages from the field, so the admin can add new tags on the fly. Added the new "topics" and "tags" fields to the "post" template. With all the right templates, fields and pages setup, we're ready to import. WordPress stores the topics, tags and the relationships of them to posts in various tables, which you'll see referenced in the SQL query below. It took some experimenting with queries in PhpMyAdmin before I figured it out. But once I got the query down, I put it in a function called importTopicsAndTags(). This function needs a connection to the WordPress database, which is passed into the function as $wpdb. For more details on $wpdb, see the first post in this thread. /** * Import WordPress topics and tags to ProcessWire * * This function assumes you will do your own $page->save(); later. * * @param PDO $wpdb Connection to WordPress database * @param Page $page The ProcessWire "post" page you want to add topics and tags to. * This page must have a populated "wpid" field. * @return string Report of what was done. * */ function importTopicsAndTags(PDO $wpdb, Page $page) { $out = ''; $sql = <<< _SQL SELECT wp_term_relationships.term_taxonomy_id, wp_term_taxonomy.taxonomy, wp_term_taxonomy.description, wp_terms.name, wp_terms.slug FROM wp_term_relationships LEFT JOIN wp_term_taxonomy ON wp_term_taxonomy.term_taxonomy_id=wp_term_relationships.term_taxonomy_id LEFT JOIN wp_terms ON wp_terms.term_id=wp_term_taxonomy.term_id WHERE wp_term_relationships.object_id=$page->wpid ORDER BY wp_term_relationships.term_order _SQL; $query = $wpdb->prepare($sql); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { if($row['taxonomy'] == 'category') { // this is a topic: find the existing topic in PW $topic = wire('pages')->get("/topics/$row[slug]/"); if($topic->id) { // if $page doesn't already have this topic, add it if(!$page->topics->has($topic)) $page->topics->add($topic); // report what we did $out .= "<div>Topic: $topic->title</div>"; } } else if($row['taxonomy'] == 'post_tag') { // this is a tag: see if we already have it in PW $tag = wire('pages')->get("/tag/$row[slug]/"); if(!$tag->id) { // we don't already have this tag, so create it $tag = new Page(); $tag->template = 'tag'; $tag->parent = '/tag/'; $tag->name = $row['slug']; $tag->title = $row['name']; $tag->save(); } // if $page doesn't already have this tag, add it if(!$page->tags->has($tag)) { $page->tags->add($tag); $out .= "<div>Tag: $tag->title</div>"; } } } return $out; }3 points
-
I'll cover these each separately. First I'll start with the images, and will come back to the others a little later when I've got more time. WordPress really only uses images for placement in body copy, so I extracted the links to them right out of there and imported them that way. I did this after the pages had already been imported. In order to keep track of which images had already been imported (so that I could feasibly run the importer multiple times without getting duplicate images), I turned on ProcessWire image "tags" option, and stored the original filename in there. Here's the function I used, which I've used many different variations of over the years with different sites. You basically just give it a $page you've already imported (but is still linking to the old site's images) and it converts the images linked in the body copy from the old site to the new. function importImages(Page $page) { if(!$page->id) return 'You need to save this page first'; $out = ''; $body = $page->body; // find all images reference in the 'body' field $regex = '{ src="(http://www.cmscritic.com/wp-content/uploads/[^"]+)"}'; if(!preg_match_all($regex, $body, $matches)) return $out; foreach($matches[0] as $key => $fullMatch) { $url = $matches[1][$key]; // image URL $tag = basename($url); // image filename $tag = wire('sanitizer')->name($tag); // sanitized filename $image = $page->images->getTag($tag); // do we already have it? if(!$image) { // we don't already have this image, import it try { $page->images->add($url); } catch(Exception $e) { $out .= "<div>ERROR importing: $url</div>"; continue; } $numAdded++; $image = $page->images->last(); // get image that was just added $status = "NEW"; } else { $status = "Existing"; } $image->tags = $tag; // replace old image URL with new image URL $body = str_replace($url, $image->url, $body); // report what we did $out .= "<div>$status: $image->basename</div>"; } // assign the updated $body back to the page $page->body = $body; // return a printable report of what was done return $out; }3 points
-
One idea came up, and was just curious about the feasibility of it: What if the "active" tab was based on the current user's language? So if I had my language set as Spanish, I'd see the Spanish tabs active (rather than default language tab) when editing a page?2 points
-
Don't forget us.. we run on ProcessWire too! http://www.cmscritic.com/feed2 points
-
class FieldtypeFieldsetOpen extends Fieldtype { /** * Appended to the name of a 'Close' version of a FieldsetOpen * */ const fieldsetCloseIdentifier = '_END'; It's just a constant string to suffix the fieldsetclose name so the admin knows what fieldset to close.2 points
-
Aah, so you want to use them for templates in the admin? How about: $opener = new Field(); $opener->type = new FieldtypeFieldsetOpen(); $opener->name = "myfieldset"; $opener->label = "Open fieldset"; $opener->save(); $closer = new Field(); $closer->type = new FieldtypeFieldsetClose(); $closer->name = "myfieldset" . FieldtypeFieldsetOpen::fieldsetCloseIdentifier; $closer->label = "Close an open fieldset"; $closer->save(); $tpl = $templates->get("custom"); $tpl->fieldgroup->add($opener); $tpl->fieldgroup->add($fields->get("body")); $tpl->fieldgroup->add($fields->get("counter")); $tpl->fieldgroup->add($closer); $tpl->fieldgroup->save();2 points
-
I use NewsBlur https://www.newsblur.com to track my RSS feeds, and it's been awesome ever since I moved away from The Old Reader, you have to pay a small yearly fee (currently $24/year), but it has a free alternative (up to 64 feeds) A great resource to find articles on javascript is http://www.echojs.com/, which is becoming more and more prominent, and is a HackerNews of sorts, but for the JS community. As far as individual blogs go, I'm a tremendously huge fan of http://www.codinghorror.com/blog/, by Jeff Atwood, a founder @ StackOverflow. For a full list of the feeds I follow (they're not that many, and they're all tech-related), visit this link: https://github.com/ponyfoo/linkdump/blob/master/rss-opml.xml2 points
-
As for the Google Reader replacement, I settled for https://feedbin.me/ and Press app for android. Both are paid, but that gives me some confidence they might be there for years to come (I also considered self hosting, but I was too lazy/busy to do that). CMS & General tect-related: http://gadgetopia.com/ CSS, standards: http://lea.verou.me/ The Web Tech/Biz Classic: http://37signals.com/svn/ Resources (this is where I found PW in 2011): http://www.webresourcesdepot.com/ I actually prefer to follow rare posting blogs that have real gems - I think that is what RSS is most suitable. I have never bothered with news sites, that have 5+ posts per day..2 points
-
Possibly just a slip, but.. you didn't mention A List Apart there? Other than that, http://www.zeldman.com/, http://davidwalsh.name and http://addyosmani.com/blog/ are quite entertaining... oh, and http://blog.ponyfoo.com/ of course! Too much good stuff to keep track of nowadays but that's what Twitter is for.2 points
-
/site/config.php $config->dbHost = 'localhost'; changes.to $config->dbHost = '127.0.0.1'; o lo contrario ?2 points
-
whut. u have in /site/assets/logs/errors.txt ? /site/config.php u set $config->sessionFingerprint=false ? what.say it for $config->sessionExpireSeconds ? u have session.db module install or uses defalt sessionions ? u look.in <?php phpinfo(); what say.it for session.cache_expire session.gc_divisor session.gc_maxlifetime session.gc_probability session.save_handler session.referer_check u chealk session dir uses writeable /site/assets/sessions/ ?2 points
-
I'm also in a rush, but there is more info on this topic here: http://processwire.com/talk/topic/3567-similar-posts-by-categories-or-tags/ The "Page" method mentioned in a few of those links is the way to go really, as it allows you to add descriptions to tags, so if you have each tag as a page (not as odd as it sounds - you want to click on a tag and see a list of pages after all ) then you can add an associated image, introduction etc - whatever your imagination can come up with Basically there is no apparent tagging system because there is no "right" way to do this in ProcessWire - it's more flexible than that.2 points
-
Hey Everyone, Before I get to the issue, thought I'd say hi. I've been using processwire for about a year now for a bunch of small web projects but haven't made a forum account yet. I've really had a great time using it. So far I haven't had any issues that haven't been solved by reading the API or going through the forums. However, it seems that time has finally come. Basically, I keep getting logged out of PW admin. There doesn't seem to be too much of a pattern governing after what amount of time it happens unfortunately. Sometimes 30seconds, sometimes 3 minutes. Today, I was getting logged out everytime I clicked a link on the admin page (any edit, new, save, etc). I saw this forum post: http://processwire.com/talk/topic/2723-strange-loading-and-logout-issues-in-the-admin/?hl=logout and followed what was done there. However, that hasn't really fixed any of my issues. There hasn't been anything in the error log (not that I really expected there to be). For all I know, this could be something on my end. I'm using the newest version of firefox for what it's worth. Any thoughts on the matter would be appreciated, I'll really try anything anyone things might work. Thanks! -Chase1 point
-
I just pushed ProcessWire v2.3.1 to the dev branch. This is a fairly major change in that it switches the DB driver from mysqli to PDO. It meant changes to a large percentage of core files. ProcessWire still supports mysqli, but doesn't attempt to use it unless a module or a template asks for it via the $db API variable. The new API variable (for the PDO driver) is $database. More about PDO at php.net If you are using the dev branch, be careful and test thoroughly with this latest commit to it. Before upgrading, you may want to double check that your PHP supports PDO by looking at your phpinfo (CMD-F or CTRL-F for "PDO"), especially if you are running PHP 5.2.x (where PDO wasn't compiled in by default). Though if you are running PHP 5.2 (vs 5.3.8+) then you may want to just stick with ProcessWire 2.3.0 and upgrade your PHP version when possible. If you are using any modules that use the procedural version of mysqli functions (vs. the $this->db object oriented versions), or type-hint mysqli in methods, then those modules will no longer work. If you come across any modules that don't work with 2.3.1, please let me know here so that I can assist the author in updating them. Note that FormBuilder is one of the modules that does not work with 2.3.1, but I have posted an update in the FormBuilder board that corrects it–so be sure to download that version if you are tracking the dev branch of ProcessWire and using FormBuilder. What this new version adds: 1. New API variable $database that refers to the PDO database. The old $db API variable is still there and refers to mysqli for any modules that continue to use it. 2. New API variable $log that lets you easily log messages or errors to the system logs. Usage: $log->message("This saves this line to messages.txt"); $log->error("This saves this line to to errors.txt"); $log->save("my-log", "This saves this line to my-log.txt"); // Get an array of the last few entries saved to the messages log $entries = $log->get('messages'); // Get an array of the last 50 entries saved to my-log $entries = $log->get('my-log', 50); Note that as always, log files are located in /site/assets/logs/. 3. Conditional autoload modules. In PHP 5.3+, modules may now specify an anonymous function OR a selector string, rather than a boolean for the 'autoload' property returned by getModuleInfo(). PW runs the anonymous function after determining the current $page, so your module can make autoload decisions based on the $page (or any other factor you'd like), if desired. Lets say that we have a module that we only want to autoload when the template is 'admin': public static function getModuleInfo() { return array( 'title' => 'Module Title', 'summary' => 'Summary text...', 'version' => 1, 'autoload' => function() { if(wire('page')->template == 'admin') return true; else return false; }); } And the same example but using a selector for autoload: public static function getModuleInfo() { return array( 'title' => 'Module Title', 'summary' => 'Summary text...', 'version' => 1, 'autoload' => 'template=admin' ); } 4. Addition of $pages->add() method. Actually $pages->add($template, $parent, [string $name], [array $values]); This function adds a new page to the database and returns it. This is for syntax convenience, but using the old method is still perfectly fine too. Here's a few examples of usage: // add a new page using template basic-page under /about/ $newpage = $pages->add('basic-page', '/about/'); // same as above, but named 'contact' $newpage = $pages->add('basic-page', '/about/', 'contact'); // same, but populate the title field too $newpage = $pages->add('basic-page', '/about/', 'contact', array('title' => 'Contact Us')); // you can also do this, specifying the values array as 3rd argument: $newpage = $pages->add('basic-page', '/about/', array('title' => 'Contact Us')); $template and $parent are required, but may be objects, IDs, or string identifiers (like name for template, or path for page). When you add a new page and don't specify a 'name', then PW will make one up, guaranteed to be unique. 5. Module files that end in '.module.php' are now supported. So rather than ClassName.module, you may use ClassName.module.php if you prefer it. The purpose here is to support text editors that determine their syntax highlighting based on the file extension. More updates being made almost daily. Please report any issues you experience. Thanks, Ryan1 point
-
Hi all, I've finally managed to set up my website where I intend to post ProcessWire tutorials. The site (lessons) is very much WIP. I have tried to make the site as responsive as possible. I have only tested in Chrome and FF. I'd rather write more lessons than test in IE to be honest so I won't pursue that... I will try to post regularly but can't make any promises as to the frequency . I intend to randomly post some pre-planned lessons. I will update this forum post everytime I post something new. If you have questions, pointers, etc about any lesson, or a request for a specific lesson, please post them here. This way, other forum members can assist in answering the questions . Thanks. /k ==================================================================== Edit: 28 August 2014 - Fist Tutorial is up (OK, it's Blog Module documentation ) Creating a Blog in ProcessWire (Blog Module how to) - 28 August 2014 [99% done] Next: 'All you ever wanted to know about ProcessWire Modules [and other cool things]' - COMING very SOON1 point
-
ProcessWire Site Profile Using Zurb Foundation 4 This is a drop-in replacement for the default ProcessWire site profile. See the live demo at: http://processwire.com/foundation/ It is mobile-first and fully responsive, capturing all the benefits of Zurb Foundation 4. Ready to be expanded upon with built-in support for deeper levels of navigation nesting in the sidebar. Pagination ready with Foundation-specific pagination output, when/if you want it. Improved search engine, relative to the basic profile. Library of Foundation-specific markup generation functions included, primary for generation of navigation (in _nav.php). Uses ProcessWire 2.3+ prepend/append template file settings making it easy to work with. It is largely stock Foundation 4 in terms of look and feel, with a few tweaks. To Install Download this profile from GitHub or mods.pw/4u. Start with a copy of ProcessWire 2.3 or newer, and its default site profile. If starting with an uninstalled copy of ProcessWire Replace the /site-default/templates/ directory with the templates directory from this profile. Replace the /site-default/config.php file with the config.php file from this profile. Run the ProcessWire installer. If starting with an already-installed copy of ProcessWire Replace the /site/templates/ directory with the templates directory from this profile. Add the following two lines to your /site/config.php file: $config->prependTemplateFile = '_init.php'; $config->appendTemplateFile = '_main.php'; Desktop Screenshot Mobile Screenshot1 point
-
Just finished another one: http://www.hirschenhotels.com Their styleguide is a bit weird for a "romantic" hotel. Futura as font and these green/red colors are not ideas of mine ;-) On the PW side pretty regular stuff, mostly core functions.1 point
-
1 point
-
Greetings, When I started this discussion, my goal was to pull together various renditions of code that were being discussed in forum discussions and create a single full example people can use to make front-end page submissions, and to also do this with photos. This is a vital part of building the kinds of sites that are really exciting with ProcessWire. I have now used the techniques detailed in this discussion for several projects, including one where I am building a completely custom front-end interface with page submission and page editing (more on that soon). In my first post in this discussion, I have the "unlink($pathname)" included in the routine. This removes the temporary image. Horst makes reference to the same code posted by Ryan. HANDLING MULTIPLE FILE-UPLOAD FIELDS IN THE SAME FORM Since starting this discussion, I have also added multiple file uploads in the same form. The steps are pretty easy. Below is my original code from post #1, with additional code for a second file-upload field (indicated with "[NEW CODE]"): <?php// First, confirm that a submission has been made if($input->post->contactname) { // Set a temporary upload location where the submitted files are stored during form processing $upload_path = $config->paths->assets . "files/contact_files/"; // New wire upload $contact_photo = new WireUpload('contact_photo'); // Reference field name in HTML form that uploads photos $contact_photo->setMaxFiles(5); $contact_photo->setOverwrite(false); $contact_photo->setDestinationPath($upload_path); $contact_photo->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif')); // Second wire upload (other_photos) [NEW CODE] $other_photos = new WireUpload('other_photos'); // Reference field name in HTML form that uploads photos $other_photos->setMaxFiles(10); // Allow 10 other photos $other_photos->setOverwrite(false); // Use the temporary location set above $other_photos->setDestinationPath($upload_path); $other_photos->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif')); // execute upload and check for errors $files = $contact_photo->execute(); $other_files = $other_photos->execute(); // [NEW CODE] // Run a count($files) test to make sure there are actually files; if so, proceed; if not, generate getErrors() if(!count($files)) { $contact_photo->error("Sorry, but you need to add a photo!"); return false; } // Set up submissions in the ProcessWire page tree $np = new Page(); // create new page object $np->template = $templates->get("contact_submission"); // Set template for pages created from form submissions $np->parent = $pages->get("/customer-service/contact-us/contact-submission-listing/"); // Set parent for pages created from form submissions // Send form submissions through ProcessWire sanitization and apply each to a template field for the new page $np->of(false); $np->title = $sanitizer->text($input->post->contactname); $np->name = $np->title; $np->contactname = $sanitizer->text($input->post->contactname); $np->email = $sanitizer->email($input->post->email); $np->comments = $sanitizer->textarea($input->post->comments); $np->save(); // Run photo upload for "contact_photo" foreach($files as $filename) { $pathname = $upload_path . $filename; $np->contact_photo->add($pathname); $np->message("Added file: $filename"); unlink($pathname); } // Run photo upload for "other_photos" [NEW CODE] foreach($other_files as $other_file) { $pathname = $upload_path . $other_file; $np->other_photos->add($pathname); $np->message("Added file: $other_file"); unlink($pathname); } // Save page again $np->save(); ?> <p>Thank you for your contact information.</p> <?php return true; } else { ?> <p> Sorry, your photo upload was not successful...</P> <?php} ?> And here is the updated submission form that would connect with the above code: <form action="/customer-service/contact/contact-success/" method="post" enctype="multipart/form-data"> <p><label for="contactname">Name:</label></p> <p><input type="text" name="contactname"></p> <p><label for="email">E-Mail:</label></p> <p><input type="email" name="email"></p> <p><label for="comments">Comments:</label></p> <p><textarea name="comments" cols="25" rows="6"></textarea></p> <p>Click the "Select Files" button below to upload your photo.</p> <input type="file" name="contact_photo" /> <input type="file" name="other_photos[]" multiple /> <button type="submit">Submit</button> </form> Points to keep in mind: 1. Add a WireUpload action for each photo-upload field, setting the rules for each one. 2. Add a separate "execute" action for each photo-upload field. 3. Add a separate foreach loop for each photo field you need. 4. If the file-upload field is for multiple files, make sure that the setMaxFiles() action matches what you set in the admin panel for that field. 5. In your form, if the file-upload field is for multiple files, specify the name with square brackets, and add the "multiple" designation. Thanks, Matthew1 point
-
Yes, you are right. Always depends on the size of a company. But my impression is that most companies want to maintain their site on their own (regarding content). Mostly because they made bad experiences with agencies charging them for every little bit, for every little change. Of course, if a company exceeds a certain size and has an annual budget for their website, they are more likely to outsource everything related to the website. But I always try to anticipate their needs for the next few years and try to implement the system as flexible as possible. Can result in little higher fixed costs but after that they usually haven't to bother me for changing little or even medium details ;-)1 point
-
Not true. First of all I don't manipulate my prices depending on a potential cash flow. And second, hotels act in a very competitive market, so I wouldn't generalize it ;-) My goal is always to deliver a tool with which my customers don't need any support from me. That's the reason why I use PW. I am not like the old school agencies which deliver TYPO3 only for supporting contracts. My available time is short, I don't want to fix things, I want to create things. Mainly because of another website I did recently: http://hotelderblauereiter.de1 point
-
Unless you had previously modified this, I doubt that's it. The default setting of 86400 is 1 day, and that's not going to cause you to get logged out every 30 seconds or 3 minutes, etc. I am wondering more about the gc_divisor and gc_probability settings that WillyC posted about, as that has more potential to answer the apparent randomness and short active sessions that you've described.1 point
-
This always seems to be an issue when translating multi-level drop down navigation to mobile. The other issue with dropdown navigation is that even on the desktop, people may miss the index pages, which might be important. The renderTopNav() function in /site/templates/_nav.php has a "repeat" option, that makes it repeat an index page as it's own first child. This solves both issues. Before I had it default to true, but set it to false later on for some unknown reason. I've switched it to be the default again.1 point
-
1 point
-
Here is code from Ryan in a post of this thread: // Run photo upload foreach($files as $filename) { $pathname = $upload_path . $filename; $np->contact_photo->add($pathname); $np->message("Added file: $filename"); unlink($pathname); // This deletes the uploaded file after it was added to the new page ($np) } unlink(); If you work with another code, you also add the files to the page. After that you have to unlink('the temp-file');1 point
-
As far as I know, all it does is add the "_END" to the name of the field, which is what is required to define the end of a fieldset. Although I did try manually adding it and it didn't work, but maybe I had something else messed up at the time.1 point
-
ha yes, it was just a slip. I really wanted to just start over with my feeds. I have added it to my new collection. AH, Twitter, I had/have an account. I just may have to start another thread and get re-started on "Who To Follow"1 point
-
Hi guys. I just happened to need a method of allowing image uploads and what do you know? There's a whole thread dedicated to it. Matthew, nice work. Thank you. I have only 2 things to add: 1. The code as is makes the assumption that each user will only ever upload one image or that there are no people with the same name. Since the title is derived from the contactname an error is thrown if a second upload is made with the same name. I added: $n = 0; $np->title = $sanitizer->text($input->post->contactname) . "-" . (++$n); It ensures each upload will get a unique ID. 2. I noticed the images uploaded to the .temp directory don't get deleted. With extensive use this will lead to lots of wasted server space as the .temp folder gets more and more bloated with duplicate images. Is there a way to solve this? You made my job very easy anyway thanks again.1 point
-
Let that sink in. Ryan, I can't absorb the knowledge you share fast enough — thank you!1 point
-
ModulesManager doesn't have tabs. Well I guess you already know you use getModuleConfigInputfields(array $data){ ... } to add configuration inputfields (not fields!) And you need to add the ConfigurableModule to the implements list (implements Module, ConfigurableModule). Now you can create a new InputfieldWrapper and add Inputfields to it. static public function getModuleConfigInputfields(array $data) { // if you have a static $defaults array for defaults you can merge them with saved ones in $data $data = array_merge(self::$defaults, $data); $fields = new InputfieldWrapper(); ... return $fields; } From there it's pretty easy. You can use all inputfield modules for inputs. It's much like creating a front-end form using API. Know my famous thread? Those inputfields are not bound to the fieldtype, like when used in the admin on pages. So the InputfieldSelect is a simple select module you can fill in options as you like. They're also used in FormBuilder. Ryan has even adapted some a little to support pure interactive inputs better. When used on a page (fields) they're actually a mix of the fieldtype and the inputfield and they depend on each other. Fieldtypes are more used to sanitize and save to db, wakup or sleep values etc, while inputfields kinda serve as an plain interface seen by the user, thus having a render() method. Some special Inputfields are more bound to functionality of other modules like "process" modules, but only remember InputfieldPageListSelect. From there it's just generaly PW API coding. So this would look like this to add a multiple ASM select static public function getModuleConfigInputfields(array $data) { $data = array_merge(self::$defaults, $data); $fieldwrapper = new InputfieldWrapper(); $modules = wire("modules"); $field = $modules->get('InputfieldAsmSelect'); $field->attr('name', 'mymodules'); $field->attr('value', $data['mymodules']); $field->label = 'Select modules.'; foreach($modules as $m) { // loop all installed modules if(strpos("$m->name","Process") === 0) $field->addOption("$m", "$m->className"); } $fieldwrapper->append($field); return $fieldwrapper; }1 point
-
This is great stuff! I'd love to see some additional detail about how you managed images, topics, tags and assigning authors. I have a few big sites to migrate. I'd also love to see your take on managing page references for related content, if applicable. Thanks for sharing! -Brent1 point
-
Short excerpt from search.php of Foundation site profile: // if the above doesn't find anything (perhaps due to MySQL minimum word // length or stopwords), switch to non-indexed phrase match if(!count($matches)) $matches = $pages->find("title|body%=$q, limit=$limit"); This is actually pretty nice idea -- use faster method first and only if it seems to fail switch to slower one. Don't know how much difference that really makes, but still. Also: there's a pager now, which is pretty obvious improvement already1 point
-
1 point
-
I need to check out that Foundation profile (and Zurb). You may want to revisit the Blog profile later on. A lot of generally useful techniques I had read about on the forum turn up there. Tags, Categories, Comments and nice examples of factoring out page builds (widgets etc.)1 point
-
You might also want to check out the new Foundation site profile, which is a variation on the Basic Site Profile included with ProcessWire, but a good one to look at next to see techniques that can scale.1 point
-
I looked at where $page->urlSegment gets retrieved, and I think for the pageNav functionality it should be done different. it reads: (Page.php, line 545) case 'urlSegment': $value = $this->fuel('input')->urlSegment1; // deprecated, but kept for backwards compatibility break; Since it says deprecated, I made a modification to markupPageArray.module line 146: if(empty($options['baseUrl'])) $pager->setBaseUrl($this->page->url . ( count($this->input->urlSegments)>0 ? '/'.implode($this->input->urlSegments,"/") . '/' : '')); Replacing $this->page->urlSegment to $this->input->urlSegments, which seems more proper to me. Should I file a bug report via Github and fork and make a pull request Ryan, or what is the best way to fix this? Or am I just messing things up by thinking this is the error while its not?1 point
-
I created an empty language pack. Go to: Admin > Setup > Languages Create a new language Drag & Drop the attached zip-file in the Language Translation Files Field. Start to edit the files. empty-lang_pack_pw_3.0.41.zip EDIT: Obsolete in latest PW Versions. Create a language pack by your own. Go to: Admin > Setup > Languages > Add New Save Press button: 'Find Files to Translate' Select all files in the box 'Translatable files in /wire/' Select files in the box 'Translatable files in /site/' which you want to add to your custom language pack Press 'Submit' Start translating Download zip or csv file by pressing the related button at the bottom of the page where translatable files are listed. Done1 point
-
Unless you have many thousands of text-heavy pages, the %= selector isn't noticeably slower than any of the others. Just to expand on Soma's answer above, it's easy to achieve 'AND' or 'OR' functionality in selectors. Nik's Selector Test module (mods.pw/2r) is great for quickly testing selectors, BTW. 'OR' first... $pages->find("body%=process|examp"); will find pages including either of the part words either side of the pipe symbol '|'. 'AND' isn't really much trickier... $pages->find("body%=process,body%=examp"); Pages found must match all selectors, so that's an 'and'. I usually build my selector string without search terms, then explode() the search terms on space characters and foreach() them on to the end of the selector string. It's all about thinking the PW way.1 point
-
Selector operator "~=" means that at least one of the fields you've defined (teaserBody, contentHeadline, contentBody) has to contain all specified words. Order doesn't matter, though. Are you absolutely sure that's the case? This could also have something to do with either stop words or length limitations, so you might want to test it with longer words and/or change selector from "~=" to "%=". This is a bit slower, but so far I've been using it pretty much everywhere without any severe performance issues.1 point
-
I saw this website after it was tweeted by smashingmag, and had to share it here http://designersfriend.co.uk/ Very risky idea, since it could become very unfriendly for non-coder visitor, but I think Andy did a great job with the planning, and I happen to find it very intuitive.1 point
-
1 point
-
That must be an error in the tutorial, since that variable appears only in that line. I looked on google for this code, and it appears to be from here http://processwire.com/talk/topic/2787-custom-menu-not-related-to-page-tree/, and the missing line would be this one: $has_children = count($child->children('include=all')) ? true : false;1 point
-
This error would indicate there's a syntax error missing closures or something. But since there's no such fault in PW and in ProcessPageSearch module, looks a bit like you're files weren't uploaded completely or something got corrupt.1 point
-
Setting the password or any value directly through API won't give you any validations. This is a functionality the inputfield is usually doing and processed in a certain way (input). If used on non interactive level the API doesn't restrict you from doing things you can't do or aren't allowed in the admin. So you ultimately you have to take care of those thing when using the API directly. So while this works: $u = new User(); $u->name = "test"; $u->of(false); $u->pass = "1234"; $u->save(); "1234" isn't a valid password if PW's password inputfield would validate it, but it's correctly saved and works. Just not recommended to code public sign up form like this. So you have to take care and add some checks to make sure its min-max length is ok and also that there's some at least 1 number and letter. If you're doing it manually and want to use the validation of the password field in PW you could use InputfieldPassword. // "_pass" = the confirm password / actually two inputs $p = new WireInputData(array("pass" => "1234", "_pass" => "1234")); $inputfield_pass = $modules->get("InputfieldPassword"); // load the inputfield module $inputfield_pass->attr("name","pass"); // set the name $inputfield_pass->processInput($p); // process and validate the field // if any errors found if($inputfield_pass->getErrors()){ print_r($inputfield_pass->getErrors(true)); } // or if coming from a form (POST) with the field names already "pass" and "_pass" $inputfield_pass = $modules->get("InputfieldPassword"); $inputfield_pass->attr("name","pass"); $inputfield_pass->processInput($input->post); // process and validate the field // if any errors found if($inputfield_pass->getErrors()){ ... } After all if you're setting a Password directly manually with the API you don't need validation, you are directly responsible to make the password strong.1 point
-
Short version: use pages for your tags and page type field to select them. In field settings (tab "Input" to be precise) there's an option called "Allow new pages to be created from this field?" -- this is how you can let your users create new tags on the fly. If you need additional details, I'm sure others will fill in those for you, I'm in a bit of a hurry right now..1 point
-
Some fun stuff just pushed to the dev branch: the core now includes a Modules Manager "Lite". The screenshots below best describe how it works. But it lets you install modules from the directory just by typing (or pasting) in the module's class name. It also provides a 1-click capability to check for a given module's updates and upgrade it when necessary. Beyond that, the modules screen is now split into tabs: Site, Core and New. Site shows just your /site/modules/, and Core shows just your /wire/modules/. The New tab is where you can install modules. I really wanted a solution that kept the actual browsing for modules out of the CMS. Not because I think it's a bad idea (it's a great idea) but because I wanted the modules directory (modules.processwire.com) to serve that purpose as much as possible, at least as a default. That way I don't have to worry about scalability as the size of the modules directory increases. Plus less automation might make the newbies be a little more careful about what they are installing and where it's coming from. The power of the automation in ModulesManager here is so powerful it scares me, so think it's better for the users that know what they are doing. Lastly, ModulesManager is one of the best modules out there and Soma does an amazing job with it. Bringing a little taste of ModulesManager into the core I thought would help both projects. Most credit for the new core "Modules Manager Lite" goes to Soma (though he doesn't yet know that). It's all built around his code lifted directly from Modules Manager. Hope that's okay Soma? Your code now powers not just the new stuff in ProcessModule, but also the new WireHttp::download function, and the new wireUnzipFile() function, all added this week. People who want the most power will still want to use Soma's Modules Manager. That does a whole lot more than the built-in one does, including installation of themes, checking for updates en-masse, and browsing and filtering through the modules directory. But now you can install ModulesManager or other modules without having to manually FTP things to your server (so long as your /site/modules/ is writable). Please let me know if you guys run into any issues with it.1 point
-
1 point
-
1 point