Leaderboard
Popular Content
Showing content with the highest reputation on 05/30/2016 in all areas
-
As a web developer I always want to improve the search results of my websites in popular search engines. Because of that I find the topic of structured data very interesting and want to learn more about them. Recently I tried out a few of the ways how to provide more information to a website and want to share my solutions. Most of the structured data can be included directly in the markup or as JSON-LD at the end of your document (right before the closing body tag). I prefer the last one, because I don't like to have bloated HTML markup. Breadcrumbs Breadcrumbs are an alternative way to show the your page hierarchy inside search results, instead of showing just the plain URL. Just like the breadcrumbs on a website. Following the example, I ended up with this code: <?php if(strlen($page->parents()) > 0) { ?> <!-- Breadcrumbs --> <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "BreadcrumbList", "itemListElement": [ <?php $positionCounter = 1; $separator = ','; foreach($page->parents() as $parent) { if($parent->id == $page->parents()->last()->id) { $separator = ''; } echo ' { "@type": "ListItem", "position": "' . $positionCounter . '", "item": { "@id": "' . $parent->httpUrl . '", "name": "' . $parent->title . '" } }' . $separator . ' '; $positionCounter++; } ?> ] } </script> <?php } ?> First I am checking if the page has parents, then I follow the follow the markup of the example. I save the position of each parent in the variable positionCounter and increase its amount after each loop. As a last step I tried to end the JSON objects by not include the separating comma after the last object. This is why I am using the separator variable. Site name and sitelinks searchbox Using JSON-LD you can provide an alternative site name and a sitelinks searchbox inside the search results (Inception ). <!-- WebSite --> <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "WebSite", "name" : "Your site name", "alternateName" : "Your alternative site name", "url": "<?= $pages->get(1)->httpUrl ?>", "potentialAction": { "@type": "SearchAction", "target": "<?= $pages->get(1)->httpUrl ?>search/?q={search_term_string}", "query-input": "required name=search_term_string" } } </script> I am not 100% sure, if the sitelinks searchbox works this way. Maybe someone who made this work before could confirm it, that would help me out. Organization For organizations you could provide a logo and links to your social profiles. <!-- Organization --> <script type="application/ld+json"> { "@context": "http://schema.org", "@type" : "Organization", "name" : "Your organization name", "url" : "<?= $pages->get(1)->httpUrl ?>", "logo": "<?= $pages->get(1)->httpUrl ?>site/templates/images/logo.png", "sameAs" : [ "https://www.facebook.com/your-organization-url", "https://www.instagram.com/your-organization-url/" // All your social profiles ] } </script> This one I think is self explanatory. Article If you have an blog or a news site you could enhance your articles with structured data with an thumbnail and author. <?php if($page->template == "post") { ?> <!-- Article --> <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "NewsArticle", "mainEntityOfPage": { "@type": "WebPage", "@id": "<?= $page->httpUrl ?>" }, "headline": "<?= $page->title ?>", "image": { "@type": "ImageObject", "url": "<?= $page->thumbnail->httpUrl ?>", // Image field in template "height": <?= $page->thumbnail->height ?>, "width": <?= $page->thumbnail->width ?> }, "datePublished": "<?= date('c', $page->created) ?>", "dateModified": "<?= date('c', $page->modified) ?>", "author": { "@type": "Person", "name": "<?= $page->createdUser->first_name . ' ' . $page->createdUser->last_name ?>" // Text fields added to core module ProcessProfile }, "publisher": { "@type": "Organization", "name": "Your organization name", "logo": { "@type": "ImageObject", "url": "<?= $pages->get(1)->httpUrl ?>site/templates/images/logo.png", "width": 244, // Width of your logo "height": 36 // Height of your logo } }, "description": "<?= $page->summary ?>" // Text field in template } </script> <?php } ?> Here I am enabling structured data for the template called post. I also have the text fields first_name and last_name added to the core module ProcessProfile, the image field thumbnail and the text field summary added to the template. Just a small note: I know you could use $config->httpHost instead of $pages->get(1)->httpUrl, but I found the second one more flexibel for changing environments where you have for example HTTPS enabled. Those are the structured data I have in use so far. I hope I haven't made a mistake, at least the testing tool doesn't complain. But if you find something, please let me know. I love how easy it is with ProcessWire to get all the information from various pages and use them in this context. As mentioned above, I am nowhere an expert with structured data, but maybe some of you would like to provide also some examples in this thread. Regards, Andreas6 points
-
Hi berechar! It just might be that all of your pages are not published. As you are logged in in Firefox, you can access those pages (that is the way PW works). But they are not accessible for guest users (which are you in other browsers).4 points
-
The latest update (v010) can remove the masthead from the Reno theme. This is available only if sticky header is on. In fact this feature uses another approach for the sticky header because only the main content is scrollable, which perhaps makes it easier to see whether the page is scrolled down or not. For the Reno theme there is a new setting "AlwaysShowSearch". Other dropdown buttons are now also supported in the HoverSaveDropdown tweak. Remind me next time not trying to modify a cloned button instance because it won't work There were numerous tweaks made to the admin configuration screen. Nested checkboxes now can't be modified if their parents are not checked, and also some space were saved by playing with field/fieldset options.3 points
-
I find things like laravel valet + php-version much more interesting for a simple dev environment compared to vagrant or docker. At least if you just need a PHP version and something mysql. For setups more involved with the infrastructure I'd also rather suggest trying Docker today, as it's Native-App Beta is doing great and the speed improvement and deployment options are just far superior. The only reason I'm currently still developing on a vm is that I'm working on different machines and don't want to hassle with updating the database back and forth. Put the vm on an external drive and done3 points
-
2 points
-
I can certainly see the intent, but I'm always cringing when I see something like that. A website is first and foremost for users and I'm not really seeing why the user should download 1.5 times the size of data, just to have lot's of (duplicate) content appended in a only machine readable format. In my mind, if it should be machine readable then supply an api to do so. It might seem verbose, but I'm more in favor of something like h-card, which is just wrapping around existing content. But in the end I'm also the one being quite glad about hardly working in the hell of SEO2 points
-
update: i'm using laragon now and love it! see this post: !!! OUTDATED !!! i'm using vagrant on win10 for all my development too. i really like it once you have the hassle of setup done. i'm now using scotchbox - i don't use the repo gebeer linked to. here is my new one: https://gitlab.com/baumrock/vagrant-pw-lamp/tree/master sorry, no time for documentation right now, but the readme from the old repo should also have some useful informations (as already linked by gebeer): https://github.com/BernhardBaumrock/vagrant-pw-lamp on win8 i had to switch GUI mode to OFF otherwise it didn't work. on win10 it was the contrary ^^ i'm too busy right know to give more help. gebeer and i have been talking about vagrant and pw development quite for some time now but it all seems too experimental to really recommend our setups to someone else... but if you want to try and have some specific questions please let me know some nice things i like and why i am using it: have a linux sandbox setup projects with "real" hosts in seconds; my workflow is like this: create a folder on my host like "example" "git bash here" clone my repo https://gitlab.com/baumrock/vagrant-pw-lamp vagrant up then i have my machine ready and can access my linux server on example.dev mailcatcher will catch all emails, so i can also test all email stuff, even when i'm offline i can do "grabpw" and get a fresh install of PW to choose from master/dev/devns i can do "backup" at any time, that will backup files + db i can do "restore", so i can move projects from one device to another i can even do "push" or "pull" of the whole website from my live server to my vagrant box, but that's a bit experimental when i'm done with the project i do "vagrant destroy", it will backup everything and keep only 1 backup and destroy the machine. so i don't mess up my host system with lots of GB of VMs ps: sorry i just realized that my repo is private... i can't make it public atm but you can pm me if you are interested2 points
-
a quick way to do this would be to use RuntimeMarkup field: in that field code you would determine the outcome of the test (check to see if this page is in a page select from the other page) and the output a field with value 1 or 0; for example if your field was called inPageSelect, then you'd get the runtime markup to output a hidden field with a value of 1 or 0, and then in your dependency you'd put show if "inPageSelect=1"2 points
-
I'm using it for all my development work. Makes setting up dev environments so much quicker and easier. No more manual installation of LAMP stack in my Linux box or fighting with WAMPP/XAMPP settings. I have one vagrant box that hosts all of my PW projects. Then I have one that brings all I need for a Drupal project. My main box is a remnant from the days where I was mainly doing Joomla projects. But it still works quite nice: https://github.com/joomlatools/joomlatools-vagrant One of these days I want to put together a box solely for PW with wireshell etc. Just didn't have the time to pull it together. Bernhard put a nice box together with some scripts for automatic PW installation and DB backups: https://github.com/BernhardBaumrock/vagrant-pw-lamp2 points
-
That's why I asked if you set (overwrite) language manually somewhere. Anyway, glad you solved.2 points
-
You also have the module SchedulePages (that works with Lazy Cron) if you want to auto-publish/unpublish pages...2 points
-
Hallo Neo! Follow the white rabbit. 1) Pages scale much better that repeaters. So if you will have really lot of banners you better use pages. Or consider commercial Repeater Matrix field. 2) You do not have to unpublish your banners. You can just add a datetime field and name it something like show_until. Then in the code just use this field in the selector and choose only pages that have show_until field value less than today. 3) If you really need to unpublish those pages you can use Lazy Cron module.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
-
This week our focus was on the server side of things rather than on the code side. Sometimes you've got to open the hood and change the oil in order to keep things running smoothly. But rather than just changing the oil, we opted to replace the entire car, moving from our compact family sedan to a turbocharged supercar, so to speak. Basically, we've had some major server upgrades this week! This post covers them in detail: https://processwire.com/blog/posts/web-hosting-changes-and-server-upgrades/1 point
-
i find it really intuitive. it looks a bit clumsy on my screencast because of the mouse but it feels different when you are touching and not pointing. i'll send you the link so you can try yourself1 point
-
Good question. These are mainly front-end stuff so I think it won't have issues with PW 2.x. I'll try it on a 2.x install.1 point
-
Hi @tpr, thanks for making this fine tool for us. Is it for PW 2.7 too, or only for PW 3.x? I cannot see a "required" property in the getModuleInfo. In the modules header comment it states ProcessWire 3.x, but then I cannnot see a namespace declaration in the file. This all makes me abit unsure, therefor I ask here. Sorry!1 point
-
Seems to be not down but empty if you look here: http://wiki.processwire.com/1 point
-
1 point
-
I've had the same error message. I had deactivated one of the languages temporarily and one user was trying to log into their account with that particular language as default. I switched the user's default language and deleted the language causing problem. That solved it for me. I think it was a very (stupid) specific issue here, don't know if anybody will ever encounter it, but I thought I'd share it anyhow1 point
-
1 point
-
"breaking into a wordpress site without knowing wordpress/php or infosec at all" -> https://notehub.org/5zo2v1 point
-
Wow, what a nice surprice to come back to office after the weekend and find so detailed answers! @Sérgio This code sample and the notion of just changing the language are invaluable. I should have guessed the simplicity, this being ProcessWire after all... Next I shall read Ryan's case study (which I believe will be enlightening!) and check adrian's Migration module in light of this. Thank you for pointing these! @hheyne Thanks for this recolletion! It sure helps me to grasp the way of thought, and proves it's not a big deal after all. @dragan As LostKobrakai already answered, they use a program that has a kind of memory of commonly used phrases and translations for certain words for a brand, so that everything stays in line and reduces the actual translating work tremendously. For starters. It's quite fascinating really, here's a link to an overview of the technologies if you're interested: http://maris.fi/en/faq/translation-memory/ It would also be irrational way to use time customer is paying by clicking through the admin interface and try to cover every single page, tab and field individually and with no way to see the whole context at a glance. This is not a small site we're talking about here after all.1 point
-
Hi, This query will give you the columns and their data types - SELECT DISTINCT TABLE_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME IN ('created') AND TABLE_SCHEMA='YourDatabaseName'; In my plain vanilla PW 3+ for example, I'm only seeing the following - field_images datetime field_img1 datetime field_page_comment int field_page_comment_votes timestamp modules timestamp page_path_history timestamp pages timestamp The end of the error message is giving you the row number the error occurred on ... 'for column 'created' at row ###'. Having the row number, and knowing the tables that contain a 'created' column, perhaps you can determine the table involved with the error?? Of course knowing the table is one thing. It's significant, but it's only a piece of the puzzle. As you already know, 1292 appears to be a mysql error number for an incorrect datetime value. So, as you said, the error has occurred a couple of times when you were logging in , or out. This brings up questions for myself also. I have never looked into what type of user session logging goes on in PW by default. Are you using some sort of module that is keeping track of user login/logout/session history? I just did a few searches and found this link from 4 years ago.. https://processwire.com/talk/topic/2082-module-process-login-history/ . Leads me to think there is no logging by default. Need to research. Just something else for me to add to the 'Things to look into' list, I guess.1 point
-
@Hardoman, It's certainly possible to have multiple menus generated by MSN on the same page. Having a desktop menu transform into a mobile menu is more about the CSS you write than MSN. There will be many ways to skin the cat, but I often use three menus per page: 1. A single-level horizontal menu of top-level pages (show at desktop widths, hide at mobile widths) 2. A vertical sidebar menu containing descendants of the root parent (show at desktop widths, hide at mobile widths) Example: $nav = $modules->get("MarkupSimpleNavigation"); echo $nav->render(null, null, $page->rootParent); 3. A mobile menu that contains all pages (hide at desktop widths, show at mobile widths)1 point
-
I agree about the error being a MySQL code...(Google n all that). Besides, in the 'pages' table, the created column is not a datetime but a timestamp. If you grep 'datetime' in /wire/ folder (dev branch), you get a result set with 15 files. Narrowing those down to Fieldtypes only you get 3 files. Narrowing these down to which ones have a column 'created' in their db schema, you get 2 files... \wire\modules\Fieldtype\FieldtypeFile.module \wire\modules\System\SystemNotifications\FieldtypeNotifications.module If you are on dev branch (I don't know about devns), my money is on #21 point
-
Hey! Welcome to the forums, skylundi! Almost everything is possible with hooks. But as it is your first post there is a chance you do not need complicated solutions. Please explain your case a littlt deeper - maybe there is some simple way we can suggest. And there is this nice module if you need just to show something on condition.1 point
-
Tutorial now available on Tuts+ here: http://webdesign.tutsplus.com/tutorials/how-to-create-an-ajax-driven-theme-for-processwire--cms-26579 for Ajax site temp laying in PW.1 point
-
You shouldn't set it manually unless you need a content from a non-current language. I asked if you do set is because if you did your site could show content from other languages. The language switcher seems OK if it changes the URL. How do you try to echo the content? (where it fails to show the correct language)1 point
-
If I remember that correctly some of the clients I'm working for are using specialized translation software, as lot's of the marketing speech is already translated somewhere, especially company specific terms and phrases. And I doubt that someone is supposed to translate those 7000 pages of tkaranka fully by hand.1 point
-
@bernhard: exactly the question I've been meaning to ask too! Syncing a site to another location periodically and preparing a failover mechanism for static data is one thing, but I'm also curious about how data gets merged back and forth in a situation like this1 point
-
I've done something similar a few years ago. Unfortunately I don't have the code anymore. From my vague recollection I've done the export this way: I built an array with all templates which contain translateable fields and the translateable fields. With this informations I built a foreach loop which loops over the the templates and writes the contents of the fields in csv-files. The import was done the same way but only the other directions ;-) The translators could do so the translations of 6 languages and got no access to the backend. I hope I could give you a helpful tip. Edit: I can remind me that we had done this with 6 independent branches without textLanguage fields. If you want to get the values you have to switch the user language for the languages to get the right values. This must also be done in the case you want to import the values. In an other project I had also to import a huge collection of values from 2 languages. If you have further questions don't hesitate ;-)1 point
-
this is not possible with no existing system on the web..... Actually I believe @JRW-910 was referring to the users not having to know any coding. Please correct me if I'm wrong, though In addition to what @mr-fan said above, I'd suggest taking a closer look at the devns branch of ProcessWire. This is the future 3.0 version, still in development, and among other features it includes a kind of a front-end editing support. Perhaps not exactly what you were looking for, but this could come in handy anyway. Other than that, Fredi provides front-end editing support right out of the box, and you can always embed admin views into the front-end by applying "&modal=1" to the URL of the edit view. This is all good to know in case you don't actually require a fully customised front-end editing experience, but would rather use the one ProcessWire provides out of the box. If it is a fully customised front-end editing feature you're looking for, that's relatively easy to achieve via the API. ProcessWire is awesome for this kind of stuff, but again: unless you really need a fully custom solution, I would suggest looking into the existing solutions first. For an example the FrontendUser module mentioned above is definitely a viable solution for the user registration part For managing permissions ProcessWire makes use of a simple role-based approach, but if you need something more specific, here are a couple of alternatives: Dynamic Roles provides a very flexible method of defining new "dynamic roles" in addition to the real ones based on various factors. There's very little in terms of permissions you can't achieve with this module. User Groups allows you to define page-specific or branch-specific permissions, and adds the new concept of "user groups" for grouping users together, regardless of roles they might have. Page Edit Per User does what the name says: assign edit access to individual users on a per-page basis. This module is a bit older already, so not entirely sure how it works with the latest versions of ProcessWire, but it's also a relatively simple one, so if it doesn't work it's easy to cook up something similar.1 point
-
For the most part I agree: classes don't have actual semantic meaning, so technically speaking they're fine, and I believe we're pretty much on the same page regarding pseudo elements too. It's just that I've recently started to emphasise pseudo-elements over classes whenever it makes sense. There are many cases where it doesn't make sense, but for something as simple as alternating background colors for predefined elements it fits the bill perfectly. I've also grown tired of trying to guess which classes I should add to my markup in order to make it easy enough to style, and I strongly dislike having to change any aspect of the markup (including generated classes) if I later on decide that I need to do something purely style-related – such as make odd items have a different background color. Pseudo elements are awesome for separation of concerns, and they can reduce the clutter quite a bit. While classes rarely add a considerable amount of extra weight to the document, unless we're talking about a serious case of classitis combined with extremely large scale use, that's another (however minor) argument against them: why add something that isn't required in the first place1 point
-
In basics my opinion is very simple, when removing stylesheets & scripts, the leftover should be good structured and meaning full Markup. Not markup that is designed to make it look better. What you see a lot in the so called frameworks is a grid system based on rows and columns. In most use cases those row divs are purely there for visualising, and they div(ide) content where the content should not be divided. Classes are meaningless for Markup, what I mean by this is that a <p> stays <p> even when the <p> has a class. So my opinion: classes are perfectly valid for visuals without altering the meaning. Pseudo elements can really help to make your markup as meaningful as possible. With pseudo you can left out that break, clear a float, etc etc, without using markup. Some people point out that html should be re-useable, so classes can be a 'pain in the ass', but my opinion is different for this as I haven't had a single project where I re-used big blocks of HTML.1 point
-
Hi JRW, first - you have the luck to came across PW Since we have a great API you could use the system inputfields and the API to create forms... https://processwire.com/talk/topic/2089-create-simple-forms-using-api/ (This is a sticky epic forum topic) And there is a module that does the heavy work for you and provide some more function to rule such forms special for frontend user managment: https://processwire.com/talk/topic/9811-frontenduser-login-logout-and-register-users-members/ (really easy module with good docs...) But you will get in trouble with this attitude on the topic this is not possible with no existing system on the web..... You will have to know the basics - you have so setup your forms and check user roles and rights...sanatize input data and process the data... since you have a complete free setup for your data - you have to create a own system to manage them - you could rely on existing tools but with a framework you always have to code something....or you mean secure without deeper skill in security things??? best regards mr-fan1 point
-
Hi, I think you might want to combine it with: $config->httpHost1 point
-
Do you set $user->language somewhere in your code? Maybe we could help more seeing your template code.1 point
-
Great! Oh yeah, there's a lot of examples here. Have in mind that importing different languages if just a matter of setting the language before importing the content, nothing more. Let's see, to begin, there's Ryan great case study on importing content from Wordpress And an example of mine, where I show how to import book contents in two languages (en and pt): <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>Import Books</title> </head> <body> <table border='1' width='100%'> <thead> <tr> <th>ID</th> <th>Title</th> </tr> </thead> <tbody> <?php // get access to WordPress wpautop() function //include("./wordpress/wp-includes/formatting.php"); $wpdb = new PDO("mysql:dbname=ricardo-wp4_db;host=localhost", "root", "root", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'")); $books = wire('pages')->get('/books/'); $sql = " SELECT * FROM wp_pods_books "; $query = $wpdb->prepare($sql); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { $book = $books->child("wpid=$row[id]"); // do we already have this book? if(!$book->id) { // create a new post $book = new Page(); $book->template = 'book'; $book->parent = $books; echo "Creating new book...\n"; } $book->of(false); $book->wpid = $row['id']; $book->name = wire('sanitizer')->pageName($row['name'], true); $en = $languages->get("default"); $book->title->setLanguageValue($en, $row['name']); $book->body->setLanguageValue($en, $row['body']); $book->introduction->setLanguageValue($en, $row['intro']); //add more fields if needed $pt = $languages->get("pt"); $book->title->setLanguageValue($pt, $row['name_pt']); $book->body->setLanguageValue($pt, $markdown->convert($row['body_pt'])); $book->introduction->setLanguageValue($pt, $markdown->convert($row['intro'])); //We need to activate portuguese page so it will appear on the front-end $book->set("status$pt", 1); // give detailed report about this post echo "<tr>" . "<td>$row[id]</td>" . "<td>$book->title</td>" . "</tr>"; $book->save(); } ?> </tbody> </table> </body> </html> You can get the gist here. And last but no least, there's Adrian's Migrator module -> https://processwire.com/talk/topic/8660-migrator/?hl=migrator1 point
-
Thanks Jan for your take on this, and welcome to the forum! I'm the other way, I don't work in hosting, only use it, so I am assuming that the Bitnami 'layer' will help reduce my learning curve. I am going to put a site on Bitnami+Google to see what I find. If I find a 'rule of thumb' guide to costs along the lines "If your VPS use is this then your cloud hosting cost would be that" then I'll post that here as that's probably the deal maker/breaker for me (since I assume the hosting experience will be roughly comparable to VPS).1 point
-
Maybe you have an autoload module or an init file somewhere that puts the output formatting off.1 point
-
The reason you would have to look for is why the homepage has output formatting turned off, because it's not usual at all. Output formatting is always turned on in front-end templates.1 point
-
A couple of reads.. https://processwire.com/talk/topic/10743-allow-page-numbers-isnt-404ing-when-content-doesnt-exist/ https://processwire.com/talk/topic/3765-404-when-using-pagination-on-multi-language-via-url-presegment-site/1 point
-
I'd really like to see a PageTree object, which can hold a (whole or partial) page tree in memory. This would allow for testing stubs and similar or the api creation of a whole tree branch at once. But sadly the PageFinder class is often dependent on mysql functionality, which by now does not have feature parity with the in memory selector engine. Also a page tree object is not really like a multidimensional array, but rather a array of pages, which optionally hold another array of children. The concept this is more like e.g. the pw form api does work with it's fieldgroups. I could imagine something like this: class Tree extends WireArray{ public function isValidItem($item) { return $item instanceof Branch; } […] } class Branch extends Wire{ protected $page; /** @var Tree $children */ protected $children; function hasChildren(){}; function getChildren(){}; function addChild(){}; […] } Edit: Really nice could also be a base Tree class, which both a PageTree as well as e.g. the Forms API could inherit from. This would also allow for easy implementation of other (custom?) tree based constructs. Nested comments for example just came to my mind.1 point
-
I've personally never been a fan of VPS hosting outside of AWS or Google. That said, I've moving an ocean of servers and sites into AWS including running on Bitnami. Most of the bitnami AMIs are free to use on AWS so all you do is pay for use of the instance and attached storage so you can make it as big or small (even free) as you want. I've personally found the setup of Bitnami instances confusing and prefer to do this myself but I also work in this space so I'm not exactly an average user.1 point
-
Thanks for the ideas. @mr-fan: I think this might be the sort of thing you're hinting at - at the top of the widget templates... <?php if( empty($options['pageStack']) ) throw new Wire404Exception(); ?> Good info in this post from Jonathan Lahijani here and some info on pageStack from Ryan here. I like this solution. @LostKobrakai: Sounds like this would work, but it seems to me there are downsides to using wireRenderFile() over $page->render(). I have a lot of different widget templates and widgets are selected by editors via a page field, so using $page->render() keeps the rendering code really simple and maintenance-free. foreach($page->widgets as $widget) { echo $widget->render(); } But if I use wireRenderFile() I need a whole chain of logic to check the template of each widget and render it with the correct file for that type of widget. Besides avoiding partial pages being directly viewable, are there other benefits of wireRenderFile() that make it preferable to $page->render()?1 point
-
@Juergen, obviously I missed your post half a year New Edition But finally I found it and redesigned the template file I provided in post 88 of another thread It is working now properly according to the google guidelines. It comes with 301 redirect to the path version that lacks the language segment which works in PW 3.0 up but not in 2.7. In this case you need to uncomment the code line which forces the redirect. Template detects if the translation is checked 'active'. Furthermore you can easily adjust selectors for the page array where the pathes are taken from. Feel free to try and use it. multilang-sitemap-xml.php.zip1 point
-
I just installed this great theme and was searching for about 15 min how to activate it. Then I came across this thread and now I know about this config setting. I totally wasn't aware of the switch in user edit profile page. Maybe because until this day I only used the default theme. I think it could save many people quite some time if this information was visible more prominently somewhere in the docs or even on the admin themes module page. What do you think?1 point
-
http://modules.processwire.com/modules/schedule-pages/ Ah, it seems you know that already? Is there something missing regarding your needs?1 point
-
I thought this was meant to be user friendly for someone without much tech skills? If you want to go for the one at a time approach, Page Table will probably be better than repeater, by the way. That way, you get to choose where all the new pages are created (you define a parent as part of the field). But as I said, if you want them to be able to just drag and drop a pile of images in one go, then you need to use an image field.1 point