Leaderboard
Popular Content
Showing content with the highest reputation on 08/03/2013 in all areas
-
The company behind WordPress is a very big supporter of open source and seems to be in it for the right reasons. I'm glad to have them powering a good chunk of the web rather than some product from Microsoft or Apple. I think WordPress has also paved a road for almost all other open source CMS products by building an audience that wasn't there before. WordPress (as a product) is fairly limited in what it really should be used for, but people push it as far as they can. Then if the need arises, they learn about and switch to other products that can do it better (like ProcessWire). WordPress market share seems to be good for the whole ecosystem (other than the persistent security issues). It's also opened many people to the idea of using open source rather than proprietary solutions... Microsoft and Apple (and so on) don't even want to touch the market because there is no money to be made in competing. So long as WordPress stays true to the original vision of being an entry level publishing tool, I think they will keep growing as a positive force. Shifting gears, but there was a question above about why there isn't a built-in tagging system in ProcessWire. You have to go beyond the term "tag" and consider what a tagging system actually is and what it does. It's a concept of relating one thing to other things. The reason ProcessWire doesn't have a tagging system is because it is a tagging system. Most know it as the Page field type in ProcessWire, which is one of the most important and fundamental types in ProcessWire. While the answer on how to use it as a literal tagging system can be found by looking in the admin side of the blog profile, I will write up some quick step-by-step instructions when I get the chance. But the primary difference between a tagging system and any other type of page reference is primarily just terminology, i.e. "tags" rather than "categories", etc.5 points
-
Hi all, I'm a big fan of the Sublime Text 2 text editor and of course of huge fan of ProcessWire, so I went ahead and created a library of PW snippets to be used with the ST2 Snippet system. I followed the PW cheat sheet, and created Advanced and Basic versions. The Advanced version contains only those seen in the advanced mode of the cheat sheet, so if you want the full set, you'll want to get both Basic and Advanced. They are on GitHub here: https://github.com/evanmcd/SublimeProcessWireSnippetsBasic https://github.com/evanmcd/SublimeProcessWireSnippetsAdvanced I've just submitted the Advanced set for inclusion into Package Manager, so hopefully that will be added soon. See the README for more info. Any feedback welcomed3 points
-
More and more, processwire has become my personal haven... I do almost no commercial work with it (I work as a dev, and for payed side-projects I suffer the dread of joomla droppings ) Made this "thing": - http://www.lisboncorrespondent.com/ This is a blog (of sorts) for my father, with make-pretend postcards sent from Portugal. It is essentially a way for me to experiment with and learn a few techs/tools: css 3d transforms (and respective headaches, cross-browser issues, etc) The wonderful angularJS framework Yeoman (build system for js apps, with grunt + bower) Processwire, of course Processwire is amazing for every crazy thing I may ever think up, and using it as a simple RESTy service provider is incredibly simple. Gotchas: This will most likely be a perma-beta site - it is for trying stuff No history back/forward or direct urls - angularJS makes it easy, but it wasn't really my concern. Will have to happen someday, though No SEO whatsoever - I'm perfectly aware that a "blog" in a one page app is a no-no, but again, just toying around Tested with Chrome, Firefox and IE 10, OSX and Win - further compatibility (and mobile) to come Hope you enjoy. And thank you, Ryan, for the wonderful gift of processwire2 points
-
I don't think you should immediately discount the example in the link provided by DaveP; because even though it was a WordPress site, that is a very small part of the example. Instead of WP posts, you would just be processing your static files that contain HTML, I think - if I understand how Jekyll works. All you need to work out is how to programmatically parse your existing pages. Alternatively, there is a module that allows you to import pages via CSV file, which might help "as it is". If not, it might at least give you an idea of how you could re-code it to suit your needs and the way that the current site is structured. http://modules.processwire.com/modules/import-pages-csv/2 points
-
In your sitemap-xml.php file, add this line at the bottom: $useMain = false;2 points
-
2 points
-
I tend not to use functions but classes with static methods to organize code into contexts. In my config I place this code for example: function MZWHelpers($className) { $path = wire('config')->paths->root . 'site/templates/_classes/'; $file = $path . $className . ".php"; if(file_exists($file)) { include $file; } } spl_autoload_register('MZWHelpers', true); I can call them in my templates via: MZWHelpers::saySomething("hello"); The class gets automatically loaded and included in every template whenever I call methods of that class, so very convenient. If you add other classes to abstract/collect specific logic, you just add another autoload in the config for that class. Anyway, that's how I do it, perhaps there's a better way.2 points
-
2 points
-
On dev branch... echo $config->version;//returns 2.3.2 - documented here echo $config->systemVersion;//returns 3 What gives? Edit: OK, answer here for $config->systemVersion class SystemUpdater extends WireData implements Module, ConfigurableModule { public static function getModuleInfo() { return array( 'title' => __('System Updater', __FILE__), // Module Title 'summary' => __('Manages system versions and upgrades.', __FILE__), // Module Summary 'permanent' => true, 'singular' => true, 'autoload' => false, /** * This version number is important, as this updater keeps the systemVersion up with this version * */ 'version' => 3, ); } protected $configData = array( // systemVersion generally represents the DB schema version, but // can represent anything about the system that's related to the individual installation. // 0 = the first version when this module was created, should remain there. 'systemVersion' => 0, );2 points
-
I've had a play with quite a few content management systems and frameworks out there and have tried my hand at teaching what I learn and sharing my pain points with others. I can relate to feeling like everyone's seen the light and they're all speaking a language you don't understand, and that can be quite frustrating. I think we all learn in different ways and some of us are example based learners while others are principle based learners. I think the most important thing is to not give up. Keep searching, keep asking, keep trying. It sounds like there's a wealth of tutorials being created by people with different learning styles and hopefully there'll be enough documentation to cover every type of learner out there Time permitting I too will be squeezing out some tutorials soon.2 points
-
Since you guys asked for it, I'll take a stab at a case study on the development process. Most of the development was done in about a week and a half. I started with the basic profile, but it ended up being something somewhat similar to the Blog profile in terms of how it's structured. Below I'll cover some details on the biggest parts of the project, which included data conversion, the template structure, the front-end development and anything else I can think of. Data Conversion from WordPress to ProcessWire One of the larger parts of the project was converting all of the data over from WordPress to ProcessWire. I wrote a conversion script so that we could re-import as many times as needed since new stories get added to cmscritic.com almost daily. In order to get the data out of WordPress, I queried the WordPress database directly (my local copy of it anyway) to extract what we needed from the tables wp_posts for the blog posts and pages, and then wp_terms, wp_term_relationships, and wp_term_taxonomy for the topics and tags. WordPress stores its TinyMCE text in a state that is something in between text and HTML, with the most obvious thing being that there are no <p> tags present in the wp_posts database. Rather than trying to figure out the full methodology behind that, I just included WP's wp-formatting.php file and ran the wpautop() function on the body text before inserting into ProcessWire. I know a lot of people have bad things to say about WordPress's architecture, but I must admit that the fact that I can just include a single file from WordPress's core without worrying about any other dependencies was a nice situation, at least in this case. In order to keep track of the WordPress pages imported into ProcessWire through repeat imports, I kept a "wpid" field in ProcessWire. That just held the WordPress post ID from the wp_posts table. That way, when importing, I could very easily tell if we needed to create a new page or modify an existing one. Another factor that had to be considered during import was that the site used a lot of "Hana code", which looked like [hana-code-insert name="something" /]. I solved this by making our own version of the Hanna code module, which was posted earlier this week. Here's an abbreviated look at how to import posts from WordPress to ProcessWire: $wpdb = new PDO("mysql:dbname=wp_cmscritic;host=localhost", "root", "root", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'")); $posts = wire('pages')->get('/posts/'); $sql = " SELECT * FROM wp_posts WHERE post_type='post' AND post_status='publish' ORDER BY post_date "; $query = $wpdb->prepare($sql); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { $post = $posts->child("wpid=$row[ID]"); // do we already have this post? if(!$post->id) { // create a new post $post = new Page(); $post->template = 'post'; $post->parent = $posts; echo "Creating new post...\n"; } $post->of(false); $post->name = wire('sanitizer')->pageName($row['post_name']); $post->title = $row['post_title']; $post->date = $row['post_date']; $post->summary = $row['post_excerpt']; $post->wpid = $row['ID']; // assign the bodycopy after adding <p> tags // the wpautop() function is from WordPress /wp-includes/wp-formatting.php $post->body = wpautop($row['post_content']); $post->save(); echo "Saved post: $post->path\n"; } What I've left out here is the importing of images, topics, tags, and setting the correct authors for each post. If anyone is interested, I'll be happy to go more in depth on that, but didn't want to overwhelm this message with code. Template File Structure This site makes use of the $config->prependTemplateFile to automatically include the file _init.php before rendering a template file, and $config->appendTemplateFile to automatically include the file _main.php after. So the /site/config.php has this: $config->prependTemplateFile = '_init.php'; $config->appendTemplateFile = '_main.php'; You may recognize this as being the same setup from the Skyscrapers profile. The _init.php includes files containing functions we want to be available to all of our templates, and set default values for the regions we populate: /site/templates/_init.php /** * Include function and hook definition files * */ require_once("./includes/render.php"); require_once("./includes/hooks.php"); /** * Initialize variables populated by templates that get output in _main.php * */ $browserTitle = $page->get('browser_title|title'); $body = "<h1>" . $page->get('headline|title') . "</h1>" . $page->body; $side = ''; $renderMain = true; // whether to include the _main.php file The includes/render.php file that is included above includes several functions for generating markup of navigation and post summaries, or any other shared markup generation functions. Examples are renderPost(), renderNav(), renderTags(). This is similar to the blog.inc file from the Blog profile except that I'm letting these functions generate and return their own markup rather than splitting them into separate view files. I personally find this easier to maintain even if it's not as MVC. The includes/hooks.php sets up any hooks I want to be present for all of my templates. I could have also done this with an autoload module, but found this to just be a little simpler since my hooks were only needed on the front-end. The main hook of interest is one that makes all posts look like they live off the root "/" level rather than "/posts/" (where they actually live). This was in order to keep consistency with the URLs as they were in WordPress, so that the new site would have all the same URL as the old site, without the need for 301 redirects. /site/templates/includes/hooks.php /** * This hook modifies the default behavior of the Page::path function (and thereby Page::url) * * The primary purpose is to redefine blog posts to be accessed at a URL off the root level * rather than under /posts/ (where they actually live). * */ wire()->addHookBefore('Page::path', function($event) { $page = $event->object; if($page->template == 'post') { // ensure that pages with template 'post' live off the root rather than '/posts/' $event->replace = true; $event->return = "/$page->name/"; } }); Our /site/templates/_main.php contains the entire markup for the overall template used site wide, from <html> to </html>. It outputs those variables we defined in _init.php in the right places. For example, $body gets output in the <div id='bodycopy'>, $side gets output in the right <aside>, and $browserTitle gets output in the <title> tag. /site/templates/_main.php <?php if($renderMain): ?> <html> <head> <title><?=$browserTitle?></title> </head> <body> <div id='masthead'> // ... </div> <div id='content'> <div id='bodycopy'><?=$body?></div> <aside id='sidebar'><?=$side?></aside> </div> <footer> // ... </footer> </body> </html> <?php endif; ?> We use the rest of the site's template files to simply populate those $body, $side and $browserTitle variables with the contents of the page. As an example, this is an abbreviated version of the /site/templates/post.php template: /site/templates/post.php // functions from /site/templates/includes/render.php $meta = renderMeta($page); $tags = renderTags($page); $authorBox = renderAuthor($page->createdUser); $comments = renderComments($page); $body = " <article class='post post-full'> <header> <h1>$page->title</h1> $meta </header> $page->body $tags $authorBox $comments </article> "; if(count($page->related)) { $side = "<h4>Related Stories</h4>" . renderNav($page->related); } What might also be of interest is the homepage template, as it handles the other part of routing of post URLs since they are living off the root rather than in /posts/. That means the homepage is what is triggering the render of each post: /site/templates/home.php if(strlen($input->urlSegment2)) { // we only accept 1 URL segment here, so 404 if there are any more throw new Wire404Exception(); } else if(strlen($input->urlSegment1)) { // render the blog post named in urlSegment1 $name = $sanitizer->pageName($input->urlSegment1); $post = $pages->get("/posts/")->child("name=$name"); if($post->id) echo $post->render(); else throw new Wire404Exception(); // tell _main.php not to include itself after this $renderMain = false; } else { // regular homepage output $limit = 7; // number of posts to render per page $posts = $pages->find("parent=/posts/, limit=$limit, sort=-date"); $body = renderPosts($posts); } The rest of the site's template files were handled in the same way. Though most were a little simpler than this. Several were simply blank, since the default values populated in _init.php were all that some needed. Front-end development using Foundation 4 The front-end was developed with the Foundation 4 CSS framework. I started with the Foundation blog template and then tweaked the markup and css till I had something that I thought was workable. Then Mike and I sent the _main.php template file back and forth a few times, tweaking and changing it further. There was no formal design process here. It was kind of a photoshop tennis (but in markup and CSS) where we collaborated on it equally, but all under Mike's direction. After a day or two of collaboration, I think we both felt like we had something that was very good for the reader, even if it didn't originate from a design in Photoshop or some other tool like that. I think it helps a lot that Foundation provides a great starting point and lends itself well to fine tuning it the way you want it. I also felt that the mobile-first methodology worked particularly well here. Comments System using Disqus We converted the comments system over to Disqus while the site was still running WordPress. This was done for a few reasons: Disqus comments provide one of the best experiences for the user, in my opinion. They also are platform agnostic, in that we could convert the whole site from WP to PW and not have to change a thing about the comments… no data conversion or importing necessary. Lastly, ProcessWire's built-in comments system is not quite as powerful as WordPress's yet, so I wanted cmscritic.com to get an upgrade in that area rather than anything else, and Disqus is definitely an upgrade from WP's comments. In order to ensure that Disqus could recognize the relations of comment threads to posts, we again made use of that $page->wpid variable that keeps the original WordPress ID, and also relates to the ID used by the Disqus comments. This is only for posts that originated in WordPress, as new posts use a ProcessWire-specific ID.1 point
-
Hi all, I've just pushed a new fully responsive site profile to Github: Unsemantic Site Profile for Processwire 2.3 After having tried seven zillion responsive grid systems, boilerplates, frameworks etc. I finally opted for Unsemantic Grid System. Mainly because it supports IE7, is lightweight and includes Compass/SASS. I've designed the profile as a starting point for development according to my needs. This includes almost no styling, an easy-to-use solution for placeholder images and three teaser boxes on the front page. In addition, I converted the .sass files that come with Unsemantic to .scss because I like the syntax better. Glad if you give it a try and find it an improvement for your workflow. You can see a preview here. Download from Github: https://github.com/christophlieck/UnsemanticSiteProfile1 point
-
Is anyone here a heavy bookmarker like I am? Typically I'll get most of my news from Hacker News and Slashdot, followed by some great blogs on a daily basis. I usually never have time to read an article in depth when I first come across it, so I'll bookmark it for later. Or, if I quickly need to get up to date on some topic, I'll do a search (usually by tags) and familiarize myself with important stuff I've bookmarked in the past. After having used browser native based bookmarking (Firefox and Chrome), then Delicious, then Diigo, then Pinboard and becoming frustrated by all of them for various reasons and limitations, I've decided to roll my own little single user (and non social) bookmarking system with ProcessWire (with Bootstrap 3 as the frontend framework). It's still a work in progress, but it takes the best of all those systems with my own power features. It also utilizes ajax for certain actions. I'll need to create a Chrome extension to tie it all together. I have to say however, after working non-stop on it for hours on end and not being able to think of anything else, it's looking slick. Damn you ProcessWire for making this so enjoyable. Jonathan1 point
-
This thread is used as a place to collect: 1. links to posts in the forum answering (repeating) newbie questions 2. links to posts in the forum and elsewhere on the net giving good insight in processwire 3. links to good articles about processwire 4. links to good tutorials posted in the forum 5. links to movie clips 6. links to posts in the forum talking about modules 7. code snippets or links to code snippets 8. Usefull Helpfiles Many good posts that answers (repeating) newbie questions or give good insight in the how and why of processwire, links to tutorial posts, (also on the net), movie clips, clarifying articles and code snippets are spread over the forum. PM me if you know a link. About this kick start see this post: http://processwire.com/talk/topic/4143-wordpress-dominates-19-of-the-web/page-2#entry40910 This is a work in progress, it takes time to make it grow bigger and better. = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = STARTING NEWBIES AND DESIGNERS Link1: Starting and growing with processwire. https://processwire.com/talk/topic/3990-another-simple-photo-gallery-tutorial/page-4#entry61069 Link2: I am basically a designer with some programming skills. My question is this: Can I go ahead to use processwire for this even though i am still learning php. http://processwire.com/talk/topic/3954-starting-out-with-website-intranet-and-internet/ Link3: Feeling overwhelmed http://processwire.com/talk/topic/3215-newbie-overwhelmed/ Link4: Questions concerning PW and it's capabilities http://processwire.com/talk/topic/1557-questions-concerning-pw-and-its-capabilities/ NEWBIES FIRST CODING QUESTIONS link1: Using a default install, I'm stepping through the tutorials, templates, etc and trying to understand the basic concepts behind processwire and at this point in time "head.inc" & "foot.inc". http://processwire.com/talk/topic/3421-footinc/ Link2: I am puzzled why some html tags are starting in head.inc but don't end in head.inc Instead they are ended in foot.inc http://processwire.com/talk/topic/3388-question-about-headinc-and-footerinc/ Link3: Question about not using ?> in processwire http://processwire.com/talk/topic/3370-question-about-missing/ Link4: After you installed processwire, it comes with a default website. What is the best way to fill in your own website ? How do you replace the default processwire website with your own ? http://processwire.com/talk/topic/3379-how-to-fill-in-your-own-website/ Link5:How much extra work/time will I have to put in, as far as understanding and writing php and getting the hang of the PW system, just to be able to create the same responsive designs I would make in HTML/CSS/Javascrip, while also achieving the easiest type of content editing capabilities (in line with what you can get with a CushyCMS type product)? http://processwire.com/talk/topic/3961-new-to-cms/ Link6: I realize what I am confused about was really something quite basic, such as where are the snippets of php code go beside on templates? Can they go on a page as the value of body field for example? http://processwire.com/talk/topic/3383-back-to-basic/ Link7: I'm stuck in something that should be very simple. http://processwire.com/talk/topic/3720-my-first-doubt-using-pw/ Link8: Several questions before I can start. http://processwire.com/talk/topic/3589-several-questions-before-i-can-start/ PROCESSWIRE CMS INSIGHTS Link1: Reading this thread makes you understand processwire real quick. http://processwire.com/talk/topic/5667-help-a-noob-get-started/ Link2: Very good case study from RayDale giving good insight in processwire http://processwire.c...a-a-case-study/ Link3: Symphony or Processwire ? Another good insight. http://getsymphony.com/discuss/thread/79645/ ARTICLES Link1: Why he choses processwire over modx http://www.mademyday.de/why-i-chose-processwire-over-modx.html COMING FROM MODX ? Link1: You've been using MODX but now you've found ProcessWire. It’s totally amazed you and you can’t wait to get started. But…you are wondering where everything is. If this is you, read on… http://processwire.c...ning-from-modx/ Link2: A MODX refugee: questions on features of ProcessWire http://processwire.com/talk/topic/3111-a-modx-refugee-questions-on-features-of-processwire/ Link3: Code comparison between modx and processwire. http://processwire.com/talk/topic/2850-processwire-for-designers/page-2#entry30349 COMING FROM DRUPAL ? Link1: How to move your site from Drupal to ProcessWire. http://processwire.c...ndpost__p__8988 PAGES IN PROCESSWIRE Link1: Understanding pages in processwire http://processwire.com/talk/topic/5667-help-a-noob-get-started/page-2#entry55820 Link2: More about the function of pages in processwire http://processwire.c...fused-by-pages/ Link3: How to hide Pages from the Topnavi via Adminmenu http://processwire.com/talk/topic/2037-how-to-hide-pages-from-the-topnavi-via-adminmenu/ TEMPLATES IN PROCESSWIRE Link1: A good post with code examples to start a template http://processwire.com/talk/topic/43-template-tutorial/ Link2: Template design a better route http://processwire.com/talk/topic/2782-template-design-better-route/ Link3: A different way of using templates http://processwire.com/talk/topic/740-a-different-way-of-using-templates-delegate-approach/ FRONT-END / BACK-END Link1: ProcessWire Setup and front-end editing made easy http://processwire.com/talk/topic/2382-processwire-setup-and-front-end-editing-made-easy/ Link2: Creating a front-end admin http://processwire.com/talk/topic/2937-creating-a-front-end-admin/ Link3: How would I build functionality and write information from the front-end to the back-end? http://processwire.com/talk/topic/2174-writing-from-front-end-to-back-end/ Link4: Is it possible to create a custom login page like a template ? http://processwire.com/talk/topic/107-custom-login/ Link5: A "members-only" section in the front-end. Integrating a member / visitor login form http://processwire.com/talk/topic/1716-integrating-a-member-visitor-login-form/ Link6: Trouble deleting pages from the front-end. http://processwire.com/talk/topic/2290-trouble-deleting-pages-from-the-frontend/ MODULE Front-end Edit. It turns the content of $page->body into a clickable area and gives the ability to frontend edit the content via tinyMCE http://processwire.com/talk/topic/3210-module-frontend-edit https://github.com/Luis85/PageInlineEdit/ MODULE Fredi, friendly frontend editing. http://processwire.com/talk/topic/3265-fredi-friendly-frontend-editing/?hl=fredi http://modules.processwire.com/modules/fredi/ MODULE Admin-bar Provides easy front-end admin bar for editing page content in ProcessWire 2.1+. http://processwire.com/talk/topic/44-is-there-way-to-get-information-about-current-user-in-templates/ http://processwire.com/talk/topic/50-adminbar/ http://modules.processwire.com/modules/admin-bar/ MULTI LANGUAGE WEBSITE IN PROCESSWIRE Link1: Multi-language website page names / URLs http://processwire.com/talk/topic/2979-multi-language-page-names-urls/ Link2: API http://processwire.com/api/multi-language-support/multi-language-urls/ Link3: The name of the default language can't be changed in Pw, but the title. http://processwire.com/talk/topic/4145-recoverable-fatal-error/#entry40611 ADD NEW USER TO YOUR WEBSITE AND PASSWORD RESET Link1: Integrating a member / visitor login form http://processwire.com/talk/topic/1716-integrating-a-member-visitor-login-form/?hl=%2Bpassword+%2Breset#entry15894 Module http://processwire.com/talk/topic/2145-module-send-user-credentials/?hl=%2Bpassword+%2Breset BASIC TUTORIALS FOR NEWBIES Link1: Approaches to categorising site content http://processwire.com/talk/topic/3579-tutorial-approaches-to-categorising-site-content/ CODE SNIPPETS AND FUNCTIONS Link1: Get page id from images object https://processwire.com/talk/topic/6176-get-page-id-from-images-object/ Link2: Function to render Bootstrap 3 carousel markup from ProcessWire images object https://gist.github.com/gebeer/11200288 .HTACCESS EXAMPLES ON YOUR HOSTING SERVER Example1: A working .htaccess file. The issues were that the .htaccess file must exist on the server before installing processwire and that the server did not allow options in the .htaccess file. After fixing that processwire could be installed on the server without any problem. Note that such restrictions might be different on your server that you need to find in the faq of your host. RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?q=$1 [L,QSA,NC] HTML KICKSTARTER Link1: How can i integrate HTML Kickstarter with processwire? http://processwire.com/talk/topic/2731-how-can-i-integrate-html-kickstarter-with-processwire/ MOVIE CLIPS Field dependencies are coming in ProcessWire 2.4. Field dependencies are basically just a way of saying that one field depends on another. It dictates which fields should be shown in a given context. https://www.youtube.com/watch?feature=player_embedded&v=hqLs9YNYKMM HELP FILES Cheatsheet Link1 Cheatsheet 1.1 as pdf file Download: http://processwire.com/talk/index.php?app=core&module=attach§ion=attach&attach_id=1299 Link2 Cheatsheet is now a processwire site (great work by Soma) http://cheatsheet.processwire.com/pages/built-in-methods-reference/pages-find-selector/ INTERVIEWS Link1: About the history and coming to be of processwire http://processwire.com/talk/topic/4084-about-ryan-and-processwire-an-interview-with-ryan-cramer/1 point
-
I've been doing the freelance thing for a while now and have a small business (very small, I am the only employee...LOL). I'm constantly on the lookout for free or inexpensive tools to make my work easier and make me more productive. I thought I would share some of the ones I use and see what else everyone else is using. My favorite ones at the moment are: Do - http://do.com - Free. Great for managing projects and tasks, and you can sync your task list and deadlines with your Google calendar. Also has an iphone app. Invoiceable - http://invoiceable.com - Free with branded footer, to remove footer one time fee of £49. I've found this to be great for creating and sending invoices. Allows for recurring invoices which is a big plus for me, and allows you to accept payment via PayPal. Google Calendar - I use this for making sure I never forget an appointment or task. Since it interfaces with do.com I can really keep track of jobs and deadlines, as well as my other obligations. Integrates well with my iPhone calendar as well. DropBox - https://www.dropbox.com/ - For saving files so I can access them elsewhere, and also for temporary backups. I'll add more as I remember them, but these are my favs at the moment. What do you use?1 point
-
I also tried, and it doesn't work. Further investigation is that the formatValue doesn't return but set $this->value; So get it fixed I need to comment out #178: //$this->value = ''; and change in render() method to instead return $this->value: public function render($value) { $this->formatValue(new NullPage(), new Field(), $value); return $this->value; } Don't know what Ryan smoked but I didn't first spotted it as it's really wierd wired.1 point
-
I think this would actually be quite easy to implement, and yes you might well be able to make use of the code that is used for the module recommend button. In fact, here is the javascript that is used for that recommendation button: http://modules.processwire.com/site/modules/FieldtypeLikes/likes.js The "number_of_likes" field could have its visibility set to "Hidden, not shown in the editor". I actually think a new option to show field values, but make them read-only would be really nice in the admin (but I digress). You could make use of diogo's http://modules.processwire.com/modules/process-admin-custom-pages/ module to easily create the table of liked pages. Before we go reinventing things, let's see what Ryan says about handing over the php code that processes the ajax call from the likes.js file.1 point
-
Here's a link to a conversation about parsing HTML pages - I used the script in question and it is very good, as long as each HTML page follows sensible structures: http://processwire.com/talk/topic/569-php-simple-html-dom1 point
-
You can use an html parser to, both, create the templates in PW and pull the content to the database. It's some work, but perfectly doable.1 point
-
I try and back it all up to Brain 1.0, but I think Brain needs an upgrade1 point
-
Is this the part you're looking for?: wire\core\Sanitizer.php: 427 // disallow some characters in selector values 428 // @todo technically we only need to disallow at begin/end of string 429: $value = str_replace(array('*', '~', '`', '$', '^', '+', '|', '<', '>', '!', '='), ' ', $value);1 point
-
Actions that create, modify or delete an entry in the DB (like save) should be done via POST requests. I find urlSegments or GET variables handy for the rest. Here's a rough skeleton of how you could do it: function edit() { ... } function save() { ... } function delete() { ... } if($input->urlSegment1 == 'edit') edit(); else if($input->post->save) save(); else if($input->post->delete) delete(); else $session->redirect($page->url . 'edit');1 point
-
If your $this->[api variable] isn't working, chances are you've overridden WireData's $this->get() or $this->__get() -- is that the case? If so, using wire('api variable'); is a fine way to go, though you may still want to fix the API variable access in whatever get() method is overridden, just to be safe. Another possibility is that you have a line that says $this->useFuel=false; That tells ProcessWire to cancel access to API variables via $this. As for why your hooks aren't being called, that's a mystery as I don't see an obvious problem with the code you posted. Though I would suggest hooking Pages::saved and Pages::deleted rather than Pages::save and Pages::delete. Add a line in your hook function like $this->message("hello!"); so that you can see in your admin that the hook was called. ProcessWire performs a redirect after page saves, which can make it easy to conclude that something isn't happening when it actually is. When you use $this->message("hello"); that gets queued between requests, which makes it useful for this kind of debugging.1 point
-
systemVersion is just an internal thing so that PW knows when it needs to apply something like modifying the schema of the database. Most ProcessWire versions don't involve changes to DB schema, so I wanted to have a separate way to track that. It's automated behind the scenes, and the systemVersion isn't useful for much else. If you ever see ProcessWire give you a message in the admin to the effect of "Applied system update #3", then it means it just made some adjustment in the system (likely to the database) and incremented the system version.1 point
-
It's interesting to read other people's perspectives on this. Although I am in Europe (UK), we are not part of mainland Europe, so I think that makes a big difference, not only to the practicalities of seeing the rest of Europe, but of attitudes towards the rest of the continent. While someone living in Spain could easily drive to Portugal or France, we have that annoying and expensive 22 miles of water to cross (the English Channel/La Manche). It doesn't make any difference to aeroplanes, but to everything else it does. As far as duration and timing of holidays goes, I come from a part of England (the North West - Liverpool, Manchester, the Beatles, the Mersey sound, Factory Records, the seat of the Industrial Revolution, the world's first passenger railway etc are all within 30 miles of my home town), where traditional Wakes Weeks still play a significant part in people's holiday schedules. That said, the ubiquity of cheap air travel has made the rest of Europe much more accessible. I know, for example, many people who have held their stag party (bachelor party) in Amsterdam in Holland, Bruges in Belgium and even Prague in the Czech Republic. If I were to make suggestions to anyone from outside Europe of where to go in Europe, some of my favourite places would, of course, be 'my' bit of England, but also London, Scotland, Normandy in France, some of the less developed parts of Spain, and just outside Europe, but not until things there settle down (if they ever do), Egypt is extraordinary.1 point
-
Maybe I've forgotten something, but I don't know why that works. I don't think we have any code specifically looking for a wildcard like that. Chances are its getting filtered out to nothing, but getting far enough in the Selector engine to let the query proceed... kind of like an id>0 selector.1 point
-
I've built a prototype page builder using Hanna codes. I create Hanna codes for different types of content blocks that you might want to display inline, inside of a RTE field. Don't forget that you can pass attributes to your Hanna code, which can be PHP and have full access to the PW API. In my example, I might have "Products" template with a bunch of categorized products, and I could set up a Hanna code called "product_list". The Hanna code accepts a parameter called 'filter' which is used as part of a PW selector in the product_list's Hanna PHP definition. This filters the products to display. Then a content editor could create something like this inside the RTE: Tortor Tristique Donec sed odio dui. Donec sed odio dui. Sed posuere consectetur est at lobortis. Etiam porta sem malesuada magna mollis euismod. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam quis risus eget urna mollis ornare vel eu leo. [[product_list filter="color=blue,category=t-shirt,limit=5" ]] Vestibulum id ligula porta felis euismod semper. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas faucibus mollis interdum. Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Donec id elit non mi porta gravida at eget metus. [[product_list filter="color=red,category=hat,limit=5" ]] Donec ullamcorper nulla non metus auctor fringilla. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Nullam quis risus eget urna mollis ornare vel eu leo. You can get very creative with this approach. For example you could also add a parameter to your hanna code called 'display' which accepts "ul" or "ol" to change the type of HTML list the Hanna code would output. Or maybe it shows just linked product titles by default but you want the option to show a short description with each title, you could can add a detail parameter of y/n to display the appropriate level of detail for a particular list. The possibilities are endless. I also recommend providing brief help text in the RTE to let editors now what Hanna codes are available, and what the acceptable parameters are. It's pretty amazing, really.1 point
-
@jmartsch: your PHP example seems like it should work properly, as far as I can tell. Have you actually tried this yet..?1 point
-
http://processwire.com/api/user-access/roles/ http://cheatsheet.processwire.com/#roles http://cheatsheet.processwire.com/#user where you see API also for checking permissions or roles (hasRole(), hasPermission()) http://processwire.com/api/variables/user/1 point
-
Images are stored in /site/assets/files/1234/ where 1234 = id of the page containing that/those image(s) .. The reference to the image (the image name, e.g. myimage.png) is stored in the database in a table which bears the image field name. E.g. if you created an image field in PW called photos, in the DB it will be named field_photos. That is where the image(s) name will be stored...The names and other data are stored as rows in that table. Hence, if you created an image field that can only hold 1 image, you will only see I row in the respective table. If you have an image field for multiple images, you will see multiple rows. The columns in the table help identify what image belongs to what page. The columns are: pages_id: (whose image is this column . This will be equivalent to the name of the folder in /site/assets/files/1234. In this case pages_id=1234) data: name of the image sort: sort order of the images; only useful when there's multiple images of course description: self explanatory modified: ditto created: ditto So how does PW know what type a field is? That information is stored in the table fields for each and every field in your site. If this sort of thing interests you, have a look in the PW database using phpMyAdmin or similar... . It will help you better understand the PW DB schema and the genius that it is..simple but effective. As for image compression, I only have limited knowledge about that at present so can't answer definitively...1 point
-
Solved with new version of FieldtypeConcat field.1 point
-
thank you a lot, wanze. i'am watching this community since february this year. its a pleasure for me to be part of such a lovely, decent and productive community - so i will do my part to it, too. also thank you for your help. you're right, my variable is the problem. i like such problems, because they are the base of my education. i'am autodidact - learning by doing, you know. for this time, you're my php-coach. thanks a lot. originally i'am lifeguard. since 2008 i run a little web&marketing-agency, because culture becomes canceled in germany more than more. till february, i worked with joomla as my working-base. php never was something i want to learn more than necessary. but in fact, i had to. joomla did the job, virtually. but its joomla, you know. now, since i found pw & its fantastic sources (also forums etc.), php & me still getting friends. I never thought that it could be so easy to be so flexible. :] for me, pw is not only cmf/cms. pw is an attitude. thanks to ryan & the pw-community! and thank you wanze. ;] best regards from the land of 'Plan B'. peace!1 point
-
I was just encountering the same problem but with another root of evil =) I used it on a date field like: $pages->find("date_field!=''") for finding pages with non empty date_fields, but it turns out, the selector engine is using the unformatted value of the fields (what else, silly me), in this case the value of an unformatted date_field is 0 and not "" (empty) which is what it looks like on the admin page. So $pages->find("date_field!=0") works just fine.1 point
-
+1 Mary, spoken from the voice of being there instead of distant theory.1 point
-
I think I've been relying on pen and paper too much and need to look up a lot of these1 point
-
I am absolutely confident that if anyone actually had > 32,000 (ext3) or > 64,000 (ext4) pages with images or other files and came to the forum asking for help, Ryan or someone else here would have a solution available in a couple of days at most. At the moment however, that hasn't yet happened, so the problem is moot.1 point
-
TK3, It is very hard to debug without more information. Please post: Using the forum code utility, the code in your template file around the problem area Details of the modules you have installed (though I don't think this is the problem) If you have a test site (front-end) that we can look at, you can post a link here too In your TEST site (local not remote), turn on debug in your /site/config.php. Are there errors reported when you load the page with the empty body? Check your /site/assets/logs/errors.txt file. Any errors reported? Do you get errors/weirdness with other fields? E.g. rich text area field? What if the field is not empty, do you still see the <span> in the output/source? Are you using the default ProcessWire install or are you using some other profile? (Foundation, Bootstrap, etc.) It could be coming from some Javascript. Are you using some JS in that template file? Edit: Searching your output above Google has led me to the module ProcessHeatmap (Heatmap by Userclicks). Are you using that? See below code from here public function setOffset(){ //we assume that the $page->body is inside main layout and add a span //hidden span indicates offset left to make fluid layout handling possible $this->page->body .= '<span class="offset" style="margin:0;padding:0;position:absolute;width:0px;height:0px;"> </span>'; }1 point
-
Zahari, not wanting to be elitist here, by the contrary. I think PW can be learnt by absolutely everyone that has the will. Better yet, all the knowledge that you get from learning PW will be useful in general and not only for working with this tool. I just think it's dangerous to start copy/pasting without understanding, and I'm not saying that you will do that, but I'm sure that lots of people will if the pieces of code are at hand... About the documentation... also not saying that it can't be better (although I really like it as it is), just that there is a concept in it. It's not that it has been left incomplete by lack of time or something. The goal of it being so small is that you can read it all in some hours and be confident that you will be ready to start right away. Truth is it worked for me and also for some others. As soon as I finished reading it, I started working with PW. And I wasn't just doing things like wondering how to change the sidebar to the left, or how to remove a link from the navigation, like I was in other CMS's that I've tested before. I was immediately building from scratch, even without being a coder. And that's priceless.1 point
-
I use Freemind and Inkscape for basic brainstorming and planning. I planned a pretty big server migration by charting it out in Inkscape and zooming in / working on each part of the chart as work proceeded. The chart ended up looking pretty cool, and it really helped put a large piece of work behind me fast. I own a copy of Illustrator but Inkscape is better IMO as a quick vector sketchbook / illustration tool. I use a little shell script to play a sound every 20 minutes so I know to look 20 feet away for 20 seconds (20/20/20 rule). My eyes have been dry so it's helpful, and a good reminder to review what I'm working on to see where I'm at and where I need to be. I use KeePassX to store passwords, which I save in a cloud-based file hosting service so the encrypted password file is synced up on my other devices as well. I use iTerm2 instead of the default Mac OS X terminal application, and fish instead of the normal shell (csh?). I like fish so far. I use nvALT for tons and tons of journaling and note-taking. I am seeking a Mac OS equivalent of Zim Wiki though, with an enforced parent/child structure visible in the sidebar. Finally I use Blender to make animated intros for videos for my clients from time to time, and Art of Illusion to sketch out ideas for rearranging furniture in my office.1 point
-
Interesting topic! I use the following - Dropbox - as you mentioned - I have been using Dropbox since it was in beta and received the invite from the founder. Freshbooks - Tracking expenses, invoices, time tracking - http://www.freshbooks.com Asana - Project management and tasks - http://www.asana.com Evernote - Notes - http://www.evernote.com Google Calendar/Gmail Wunderlist is pretty good on Mac - http://www.wunderlist.com Jason1 point
-
The folders contain images uploaded on a page. The folder names are the IDs of the pages. See the following topic for a discussion about this issue: http://processwire.com/talk/topic/992-problem-with-assetsfiles-folder/ And an empty folder cleaner http://processwire.com/talk/topic/1585-module-clean-empty-directories-from-siteassetsfiles/ http://modules.processwire.com/modules/page-clean-empty-dirs/1 point
-
This hasn't been asked, but wanted to cover how the permissions and publish workflow work on the site. It has a very simple, though nice setup, where authors can submit new posts but can't edit already published posts, nor can they edit unpublished posts by other authors. It enables Mike to have full control over any content that gets published on the site, while still allowing easy submission and edits for the authors. Post workflow All of the authors have a role called "author" with page-edit permission. On the "post" template, the boxes for "edit" and "create" are checked for this "author" role. This site also makes use of the page-publish permission, which is an optional one in ProcessWire that you can add just by creating a new permission and naming it "page-publish". Once present, it modifies the behavior of the usual page-edit permission, so that one must also have page-publish in order to publish pages or edit already published pages. The "author" role does not have page-publish permission. As a result, authors on the site can submit posts but can't publish them. Nor can they edit already published posts. In this manner, Mike has final say on anything that gets posted to the site. Post ownership The default behavior in ProcessWire is that the Role settings control all access... meaning all users with role "author" would be able to do the same things, on the same pages. In this case, we don't want one author to be able to edit an unpublished/pending post created by another author. This was easily accomplished by adding a hook to /site/templates/admin.php: /** * Prevent users from being able to edit pages created by other users of the same role * * This basically enforces an 'owner' for pages * */ wire()->addHookAfter('Page::editable', function($event) { if(!$event->return) return; // already determined user has no access if(wire('user')->isSuperuser()) return; // superuser always allowed $page = $event->object; // if user that created the page is not the current user, don't give them access if($page->createdUser->id != wire('user')->id) $event->return = false; }); Planned workflow improvements Currently an author has to let Mike know "hey my article is ready to be published, can you take a look?". This is done by email, I'm assuming. An addition I'd like to make is to add a Page reference field called "publish_status" where the author can select from: DRAFT: This is a work in progress (default) PUBLISH: Ready for review and publishing CHANGE: Changes requested - see editor notes DELETE: Request deletion Beyond that, there is also an "editor_notes" text field that only appears in the admin. It's a place where Mike and the author can communicate, if necessary, about the publish status. This editor_notes field doesn't appear on the front-end of the site. All this can be done in ProcessWire just by creating a new field and adding these as selectable page references. That's easy enough, but I want to make it so that it notifies both Mike (the reviewer) and the author by email, every time there is a change in publish status or to the editor_notes. This will be done via another hook in the /site/templates/admin.php: wire()->addHookAfter('Page::saveReady', function($event) { // get the page about to be saved $page = $event->arguments(0); // if this isn't a post, don't continue if($page->template != 'post' || !$page->id) return; // if this post wasn't made by an "author" don't continue if(!$page->createdUser->hasRole('author')) return; $subject = ''; $message = ''; if($page->isChanged('publish_status') || $page->isChanged('editor_notes')) { // the publish status or editor notes have changed $subject = "CMSCritic post publish status"; $notes = $page->isChanged('editor_notes') ? "Notes: $page->editor_notes" : ""; $message = " Title: $page->title\n URL: $page->httpUrl\n Status: {$page->publish_status->title}\n $notes "; } else if($page->isChanged('status') && !$page->is(Page::statusUnpublished)) { // page was just published $subject = "CMSCritic post published"; $message = "The post $page->httpUrl has been published!"; } if($message) { $reviewer = wire('users')->get('mike'); $author = $page->createdUser; mail("$reviewer->email, $author->email", $subject, $message); $this->message("Email sent: $subject"); } }); Mike, if you are reading this, does this sound useful to you?1 point
-
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>1 point
-
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; }1 point
-
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; }1 point
-
You're welcome. Here's a good overview how Hook works: http://processwire.com/api/hooks/ Also checkout the captain which shows you all the hooks available: http://somatonic.github.io/Captain-Hook/ And here an example, written in the browser and not tested: // Inside your autoload module you have installed... public function init() { $this->addHookAfter('ProcessPageEdit::buildForm', $this, 'hideFields'); } public function hideFields(HookEvent $event) { // Do nothing if we don't edit a user if ($this->page->template != 'user') return; // Get the form instance returned from the hooked method $form = $event->return; // Define fields to hide per role $hideFields = array( 'role1' => array('field1', 'field40'), 'role2' => array('field5', 'field2'), ); // Hide the fields foreach ($hideFields as $role => $fields) { if ($this->user->hasRole($role)) { foreach ($fields as $field) { $f = $form->get($field); $f->collapsed = Inputfield::collapsedHidden; } } } $event->return = $form; }1 point
-
How difficult is it to move Processwire lets say I am doing like client.mydomain.com and then when done and the client is happy with it then move it to their root domain myclientdomain.com1 point
-
You could accomplish the above in various ways. I'll cover two: Option 1: Structure -people --john ---organization 1, ceo, 2010-2012 ---organization 2, board member, 2009-current --mike --etc. The above would have child pages of each person that represents their organization connections. The fields on that template would be: organization (single page select to /organizations/) position or title (text, their position at the organization) start_year (integer) end_year (integer) Option 2: Repeater This is the option I would use, and it's perfect for this sort of thing. It's basically doing the same thing as option 1, but making it simpler and disconnecting it from the structure. You'd create a new field using ProcessWire's repeater fieldtype, perhaps naming it 'organizations' or 'person_organizations'. Then add the same fields mentioned in the bulleted list above. Add this new 'person_organizations' field to your 'person' template. Now you can define as much meta information for that person<->organization relationship as you want to. More on how to use ProcessWire's Repeater fieldtype1 point
-
Thanks for the question @tinacious and answers @all, it's a reminder for me to do this stuff before I go live, can't have too many of them... Thanks for the list @formmailer, the only two I would add are: don't forget that you can have two config files, one to control your local (MAMP XAMP etc) environment (inc' db credentials etc) and another for the live/remote, see Maintaining a separate development configuration file. This is not really a thing to do at go-live time, but seemed worth noting in this context once you have two config files, for your local file only, enable "$config->debug = true;" — I have just started doing this and already it uncovered something slightly dirty in my PHP for me to tidy up. This ability to maintain local and remote configs is for me yet another differentiator for PW where something small yet really useful in the real-world has made it into production, a testament to the thought and care gone in to this product. PS: UPDATE: I just remembered that assuming you use the above dual config files setup you need to configure your FTP client to not transfer a file called config-dev.php or the remote env' thinks it is a dev env I just tripped myself over with that.1 point
-
I actually am so lazy I have following in my config.php: switch ($_SERVER['HTTP_HOST']){ case 'www.domain.com': case 'domain.com': define('DEV_ENVIROMENT', 'LIVE'); break; case 'beta.domain.com': case 'staging.domain.com': define('DEV_ENVIROMENT', 'STAGING'); break; case 'www.domain.local': case 'domain.local': case '10.0.2.2': default: define('DEV_ENVIROMENT','LOCALHOST'); break; } on the top, and then on the bottom I have groups of configuration from the original generated config.php (well, one is generated, rest is copy-paste-change) in ifs: if ('LOCALHOST' === DEV_ENVIROMENT): This way, I only ddeploy database & code and everything is running like nothing ever changed :3 Of course, deployment strategies differ, when you need to sync data back and forth-for instance, on this one system I prepare and test any new stuff (even in db), import live (changed db) and recreate the db part of the new stuff (already programmed and tested) and push it back to production (or staging).1 point