Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 11/27/2018 in all areas

  1. I guess it should be doable by extending WireDT accordingly and implementing fitting getDatabaseSchema and savePageField/loadPageField methods as well as making sleepValue/wakeupValue with arrayish data instead of plain strings, a lot like the Events fieldtype but without the multiple value (EventsArray) stuff. Meanwhile reproduced and working on a solution. Should be ready in a few days at most. Meanwhile, I haven't been completely lazy: DatetimeAdvanced v1.0.3 supports custom subfields and works together with Lister's subfield selectors.
    3 points
  2. Hey, no one has to apologize for their criticism! I am very grateful for it and have learned something new again! Thanks all for your help! I have revised the tutorial and hope that others can learn something too. Greetings, Martin
    3 points
  3. With around 3,400 employees worldwide, IMS Gear develops and produces specific drive solutions for international customers. In addition to the focus on the automotive industry, the focus is on applications for industry and e-mobility concepts. Finding new employees is important for the day-to-day business of IMS Gear. For this reason our agency designconcepts developed a job portal, where potential employees can easily inform themselves about the company, the application process and find the job they are looking for. The website was build with help of the framework UIkit. jobs.imsgear.com Features: Job finder Job offer PDF Newsletter Fly-in information pages Job finder Core of the website is the job exchange with the job finder. Here you get a list of all available jobs which you can filter by three main areas (categories, task areas and locations). Or you can type in anything in the search field and filter by various keys (for example ID, title, country and hidden tags). The job finder was build with jQuery Typeahead, which was really helpful in building this complex logic. If you want to know which job is the closest to you, you can sort them by distance. Job offer PDF Every job offer has a printable PDF version for newspapers or other job platforms. The job offer PDF can be created by checking a checkbox in the back-end and saving the page. The PDF will then be created with all needed fields of that page and DocRaptor. This workflow is really easy for editors and guarantees a consistent layout for all created PDFs. Newsletter If there is no job for you available at the moment, you can subscribe to a newsletter with your areas of interest. Then you will be notified daily if a job is available with your interests. Instead of using a separate newsletter tool, the nice module Newsletter Subscription was used to manage subscribers. The newsletter will be send via a shell script executed by a daily cron job. Modules used: Continents and Countries Front-End Page Editor Functional Fields Markup Sitemap XML Newsletter Subscription ProCache Repeater Matrix Tracy Debugger Upgrades Wire Mail SMTP Regards, Andreas
    3 points
  4. In my head this (and also the hints regarding the flags) was positive ? Not necessarily, especially if you throw in a disclaimer in there. Many times it is about the journey, not the destination. Whereas you set out to write a tutorial, from where I stand, that in itself is only part of the story. The other part of the story is what you are unconsciously telling newbies. That story says, hey, look guys, I found this new toy and look at what I can already do with it ?. Agree. That's what I like so much about the community. Throw in an idea and get valuable feedback instantly. There will also be times where you share something and get the hint that what you've done is already available in some way. At least that happened to me several times. Nothing about that is negative. It's just holding up the quality of the forum and clarifying why your approach might be different and better for special situations. I'd highly encourage you to continue writing tutorials. It will help you a lot and likely it will also help others. And nobody (here) knows everything. Except Ryan, of course ??
    3 points
  5. Hello, I'm very new to ProcessWire but already fell in love with this CMS/CMF! I just finished my first small project and as I saw a lot of questions and different answers in this forum on how to set up a nice language switcher for your website, I decided to write my first tutorial. ---------- Please note: I rewrote this tutorial since I was made aware and learned that flags should not be used for language selectors! There are some threads here in the forum (and from external sources) where this question is discussed: https://processwire.com/talk/topic/13196-adding-image-field-to-language/ http://daily.unitedlanguagegroup.com/stories/editorials/inside-design-language-selector-no-flags https://processwire.com/talk/topic/16524-extending-languages-template/ http://www.flagsarenotlanguages.com/blog/why-flags-do-not-represent-language/ https://processwire.com/talk/topic/14241-language-names-and-utf8-page-names/ Thanks, @ottogal @bernhard @jmartsch @kongondo an all others for your hints! ---------- TUTORIAL - Set up a nice language switcher for your website - here we go: This will be the desired result! Step 1) Setup at least 2 languages in your PW install. In my case it's German (default language) + English: Step 2) Add a custom field Type = Text Name = languagecode This will hold the ISO 639-1 two-letter language code for the respective language. The field is needed to provide a simple method for outputting the language code in your templates. Without this field, you will need to programmatically construct your two-letter language code output via PHP (at least for the default language, as ProcessWire doesn't allow to rename the default language and it will always be called default). Here is an overview for ISO 639-1 two-letter language codes: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes Step 3) Add this field to the system template: language. To achieve this, go to Setup / Templates and activate the filter Show system templates: Now you can add the previously created field languagecode to the language template. Step 4) Edit your languages and fill in the appropriate values. a) default (German) Name = default (this can't be changed and is read only) Title = Deutsch (in both language tabs! - this is important as your visitor should always see his language item ... in his language) languagecode = de b) english (English) Name = english Title = English (in both language tabs! - this is important as your visitor should always see his language item ... in his language) languagecode = en Step 5) Now we are ready to write our template output! As we already have the appropriate two-letter ISO language code (languagecode field), we can use this in our html lang property: <html lang="<?php echo $user->language->languagecode; ?>"> Also the rel alternate output in the html head is simple. Put the following code within your <head></head> area: <?php // Handle output of 'hreflang' link tags for multi-language (SEO!) foreach ($languages as $language) { if (!$page->viewable($language)) { continue; } // Get the http URL for this page in the given language $url = $page->localHttpUrl($language); // Get the language code using custom languagecode field $languagecode = $language->languagecode; echo PHP_EOL.'<link rel="alternate" hreflang="'.$languagecode.'" href="'.$url.'">'; } ?> In my sample I've used Boostrap 4 and the code below shows a complete navbar with our language switcher (BTW the language switcher will always be visible, even when the bootstrap navbar is collapsed): <nav id="mainnav" class="navbar navbar-expand-lg navbar-light px-4 px-md-5 sticky-top"> <a class="navbar-brand" href="<?php echo $config->urls->root; ?>"> <img src="<?php echo $config->urls->templates; ?>images/logo-rund-80x80.png" alt=""> Your Site Title </a> <ul class="navbar-nav ml-auto mr-3 mr-lg-0 order-lg-last d-none d-xs-custom-flex language-switcher" aria-label="<?php echo __('Sprache wechseln') ?>"> <?php echo '<li class="nav-item dropdown">'; // Construct the language prompt in the current user language $prompt = $user->language->title.' ('.strtoupper($user->language->languagecode).')'; // Current language = dropdown-toggle echo '<a class="nav-link dropdown-toggle" href="#languages" id="language-select" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">'; echo '<span class="world-icon"></span><span class="sr-only">'._x('(aktuelle Sprache)', 'navigation').': </span> '.$prompt; echo '</a>'; echo '<div id="languages" class="dropdown-menu dropdown-menu-right" aria-labelledby="language-select">'; foreach ($languages as $language) { // Get the http URL for current page in the given language $url = $page->localHttpUrl($language); // Construct the language prompt in the given language $prompt = $language->title.' ('.strtoupper($language->languagecode).')'; // Next language item (except current language) if ($user->language->id != $language->id) { if (!$page->viewable($language)) { echo '<span class="dropdown-item disabled">'.$prompt.'</span>'; } else { echo '<a class="dropdown-item" href="'.$url.'">'.$prompt.'</a>'; } } } echo '</div>'; echo '</li>'; ?> </ul> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarMainMenu" aria-controls="navbarMainMenu" aria-expanded="false" aria-label="<?php echo __('Menü einblenden / ausblenden') ?>"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse my-3 my-lg-0" id="navbarMainMenu"> <ul class="navbar-nav mr-auto"> <?php // Top navigation consists of homepage and its visible children foreach ($homepage->and($homepage->children("template=main-page|news|contact-points")) as $item) { if ($item->id == $page->rootParent->id) { echo '<li class="nav-item active">'; echo '<a class="nav-link" href="'.$item->url.'">'.$item->title.'<span class="sr-only"> '._x('(aktuelle Seite)', 'navigation').'</span></a>'; echo '</li>'; } else { echo '<li class="nav-item">'; echo '<a class="nav-link" href="'.$item->url.'">'.$item->title.'</a>'; echo '</li>'; } } ?> </ul> </div> </nav> That's it! I hope you will like my tutorial and if there are any questions, critics or improvements please let me know! Thanks, Martin
    2 points
  6. https://www.spiria.com After several sites made with ProcessWire, Spiria decided it was time to get rid of its cumbersome Drupal site. To be honest, ProcessWire is still difficult to sell to customers, because this CMS/CMF is not as well known as the most popular ones. The migration to ProcessWire therefore served several purposes: Eliminate the frustrations experienced with Drupal (especially with image management and some structural problems). Allow integrators to learn the CMS during quiet periods, when they are not needed on other projects. Promote the CMS by adopting it. The challenges were many, but by no means insolvent, thanks to the great versatility of this programming framework. Indeed, if ProcessWire can be considered as a CMS in its own right, it also offers all the advantages of a CMF (Content Management Framework). Unlike other solutions, the programmer is not forced to follow the proposed model and can integrate his ways of doing things. The blog The site includes a very active blog where visuals abound. It was essential to cache the various dynamic components. For example, in all sections of the blog, there is a list of recent articles, a list of "short technical news", another list from the same author, a classification by category. In short, these lists evolve independently. ProcessWire's cache system, including its ability to classify by namespace, has significantly improved loading speed. Cache file management has been placed in a "saved" hook in the useful "ready.php" file. Data migration Importing the blog data was complex because at the time the site was designed in Drupal, programmers had not been used the easily translatable "entities", so each article resided in two different "nodes" (pages). We would have liked to use the core ProcessWire import module, but it does not yet take into account multilingual fields. However, we have used this code as a basis for building our own import module. This is one of ProcessWire's great qualities, as a CMF, it is easy to use existing code to design your own solutions. Reproduce the layout The current layout of the site has been reproduced exactly as it serves the company's needs very well. ProcessWire has simplified the work in many ways. Apart from the blog, which is very structured, the other sections of the site are more free, especially the case study section ("Our Work"). The use of page reference fields has particularly helped developers. As everything is a page in ProcessWire, you can create a pseudo relational database within the site itself. The administrator user becomes more aware of the data hierarchy and has better control over the data. Programming architecture The separation between controllers and Twig visualization files facilitates the management of the multiple components of the site. We haven't really explored the "regions" of ProcessWire, because we prefer not to mix these aspects of programming. This greatly facilitates the timely arrival of programmers in our department, used to an MVC structure, because they have a better understanding of what does what. The Search Once again, we were able to simplify what had been done in Drupal. There are two types of searches on the site, the blog search and the more general search on page 404 ( https://www.spiria.com/potato). The Drupal site search was driven by an Apache Solr server in Drupal. We decided to rely on the ease of ProcessWire and the Typeahead library (for the blog), because we didn't need the power of Solr (or Elasticsearch) anyway. Work to improve performance still needs to be done in this area. We would have liked to have seen the excellent search tool offered on the administrative side available on the frontend. We have not yet had time to explore the possibility of harnessing this code from the core of ProcessWire. Our wish here is that the CMS designer, Ryan Cramer, sees this as an opportunity to offer an exciting new feature to his CMS! Powerful modules We have the excellent modules ProCache (static caching), ProFields (fields that greatly improve the functionality of existing fields) and ListerPro (data search and processing tool). As the site is installed on a nginx server, we have ruled out ProCache for the moment and we are satisfied with the use of the cache() function alone. The ProFields fields are a blessing just like ListerPro. This last module is very useful to correct, for example, import errors (we had more than 800 blog articles, some of which date back to 2013). We used a functional field to gather translations of terms that would normally have remained hard coded and difficult to access in the translation interface (an aspect to be improved in ProcessWire, in our opinion). By grouping translations in a single page, site administrators can easily change or correct terms. Language management What remains a very small irritant for us is the management of languages, which is fantastic in many ways. The fact that there is a default language is both a blessing and a problem. For example, in 2013, blog articles were not systematically translated. We experienced the same situation with a customer's site. If the article is only in English, no problem, we only have to not check French as an active language. However, if the article is only in French, we are still required to create the page in English and make tricks in the code, thanks in particular to a checkbox such as "Not present in English" to reproduce the behaviour naturally present for English (or any language deemed by default). Perhaps there is a more elegant solution here that we have not yet discovered. It's not much, but some clients don't see why there are two ways to do it here. In conclusion In any case, ProcessWire's great qualities continue to appeal to programmers, integrators, graphic designers, users and even our UI/UX expert. The solidity of the CMS/CMF, its functionalities all translated into objects/variables ($pages, $page, $config, $sanitizer, $input... the list is long) allows us to systematize our workflow, easily recover code and reduce production costs. Although it is dangerous to offer only a CMS solution to our customers (hammer syndrome that only sees nails), it is tempting to consider ProcessWire as the Swiss Army knife par excellence of Web programming. As mentioned above, the CMF is suitable for all situations, has very good security tools and its designer has successfully improved PHP methods to make programming very pleasant and intuitive. For us, migrating the company's website to this platform was the best tribute we could pay to its designer, @ryan.
    2 points
  7. Security Report: FYI TL;DR: Our module does not use the vulnerable PHP files. We are OK; nothing to see here ?. You might have come across reports that Blueimp jQuery File Upload on which the module JqueryFileUpload is based had some vulnerabilities that had gone undetected for 8 years! The vulnerabilities, that have since been fixed, had to do with the server-side application examples that ship with Blueimp jQuery File Upload, specifically the two PHP files Upload.php and UploadHandler.php. Our ProcessWire JqueryFileUpload module is not in any way affected by the vulnerability. Here's why: We don't use Upload.php and UploadHandler.php nor any server-side samples that might ship with Blueimp jQuery File Upload. We use ProcessWire's WireUpload Class instead. We don't ship our module with these files. We use Blueimp jQuery File Upload purely for its client-side upload capabilities (only the JavaScript). Blueimp jQuery File Upload aside, we operate a very tight ship with our module. These include: Not everyone can upload files. That decision is left to the developer. All files are validated for both MIME types and file extensions. Only extensions specified by admin are allowed to go through to validation. All uploads are stored in a temporary folder pending validation. The location of the temporary folder is configurable. One can set either a web-accessible folder (e.g. in cases where one wants to show thumbnails of uploaded images) or a hidden one. All actions sent from client-side are validated against settings stored server-side. For instance, uploading, listing and deleting files. So, changing a JSON setting sent to the module client-side has no effect server-side. We use CSRF. Etc... Here are the relevant links to the above mentioned (but now fixed) exploits. https://blogs.akamai.com/sitr/2018/10/having-the-security-rug-pulled-out-from-under-you.html https://www.exploit-db.com/exploits/45584 https://github.com/blueimp/jQuery-File-Upload/blob/master/VULNERABILITIES.md https://github.com/blueimp/jQuery-File-Upload/blob/master/SECURITY.md In conclusion, this is just for your information, in case you were wondering or came across it. We are not affected and we didn't have to patch anything. Having said that, as per our OP, we urge all developers who use this module to exercise best practices to secure their applications.
    2 points
  8. Thanks @eelkenet, fixed in v0.1.4.
    2 points
  9. @jmartsch you are right! -again ... ? Corrected! This was the wrong attachment version. The forum software doesn't make it easy to exchange screenshots or to choose the right attachment.
    2 points
  10. I installed the module (v0.1.3) on an existing site, running PW in the current Master release, v3.0.98 on Php 7.2. After enabling the module for a regular Fieldset (Open) I kept running into this error: Method InputfieldFieldsetOpen::wrapClass does not exist or is not callable in this context This is because Inputfield::wrapClass() has not been added to the Master yet, it is only available on the ProcessWire dev release (currently 3.0.119). The fix for this issue is to replace lines 107-109 with: // Add classes to inputfield $inputfield->wrapClass .= ' MinimalFieldset'; if(!$field->no_spacing) $inputfield->wrapClass .= ' MinimalFieldsetSpaced';
    2 points
  11. Thank you @Gadgetto for taking our improvements into account and updating you tutorial. However, I spotted a small error in your screencast/animation: If the language is switched to english then the word "german" instead of "Deutsch" appears. As you wrote yourself in your tutorial, the language should be written in the language itself ? I am happy to welcome another happy ProcessWire addict into our community ?
    2 points
  12. @bernhard You're right, my comment really sounds a bit weird, and I apologize for that. (I became aware of that soon after having posted.) Of course, if someone uses a flag to indicate the German language, it's not "wrong" to take the Austrian one and not the German one - both are equally suitable for this purpose, or unsuitable. Just because of a possible ambiguity of this kind they both are unsuitable - that's the point of my remark. I also apologize to @Gadgetto: My intention was not to criticize, but to give some well-meant advice.
    2 points
  13. I put this feature request in a couple months ago which relates to this conversation about migrating structural changes: https://github.com/processwire/processwire-requests/issues/230
    2 points
  14. Martin, sorry if we came across in a not-so-positive way ?. Please don't take it personally; I'm pretty certain it is the code that was being critiqued (and given that what you wrote was a tutorial, meaning others could learn from it and apply its principles, it's understandable that suggestions were made on how it could be improved). I promise you, this is a very friendly forum ?. Not necessarily, especially if you throw in a disclaimer in there. Many times it is about the journey, not the destination. Whereas you set out to write a tutorial, from where I stand, that in itself is only part of the story. The other part of the story is what you are unconsciously telling newbies. That story says, hey, look guys, I found this new toy and look at what I can already do with it ?.
    2 points
  15. After a while it became even easier for me to just copy&paste together new fields/templates instead of creating them in the UI. There's certainly a transition phase, though. The UI I use mostly for when I'm not sure how to build something yet. For any project with a somewhat longer period of active development/maintainence I'd really suggest anyone trying it.
    2 points
  16. emplate Field Widths Adds a "Field widths" field to Edit Template that allows you to quickly set the widths of inputfields in the template. Since v0.2.0 the module also adds a similar field to the settings of Edit Field for Repeater, FieldsetPage and Repeater Matrix allowing you to quickly set the widths of inputfields within the Repeater/FieldsetPage field, or within each Repeater Matrix type. Note: widths are only saved if the edit form is submitted with the "Field widths" field in an open (non-collapsed) state. Edit template Edit Field: Repeater Edit Field: Repeater Matrix Why? When setting up a new template/repeater or trying out different field layouts I find it a bit slow and tedious to have to open each field individually in a modal just to set the width. This module speeds up the process. Config options You can set the default presentation of the "Field widths" field to collapsed or open. Widths entered into the "Field widths" field are only applied if the edit form is submitted with the field in an open (non-collapsed) state. "Collapsed" is the recommended setting if you think you might also use core inputs for setting field widths in a template context. You can choose Name or Label as the primary identifier shown for the field. The unchosen alternative will become the title attribute shown on hover. You can choose to show the original field width next to the template context field width. https://github.com/Toutouwai/TemplateFieldWidths https://modules.processwire.com/modules/template-field-widths/
    1 point
  17. Building your very own custom Fieldtypes in ProcessWire seems to be hard, but it actually is not, once you get the concept. In this post I'll share a simple and as minimalistic module as it can get that everybody can use as a boilerplate for his own Fieldtypes. A Fieldtype that does not store any information in the database A Fieldtype that stores information in the database (to be done) Make your Fieldtype configurable 1. A Fieldtype that does not store any information in the database Some of you might know the excellent RuntimeMarkup module by @kongondo. I've used it a lot in the past, but I get more and more into developing custom fieldtypes rather than hacking the runtime module to my needs. That has several advantages, but it has also one major drawback: It is always a pain to setup a new Fieldtype, because there are lots of methods (see the base class /wire/core/Fieldtype.php) and you have to know which methods you need, which ones you have to remove and adopt etc.; Not any more! Ryan has developed a showcase module (the Events Fieldtype) to learn from, but when I first peaked into it, it felt quite complex and I thought it would be a lot of effort to learn Fieldtype development). There are also some easy and small Fieldtypes to learn from, like the FieldtypeCheckbox. But all of them require a good understanding of what is going on, you need to modify existing config inputfields that might have been added to that fieldtype and afterall it's not as easy as it could be. With my new approach I plan to use a boilerplate fieldtype to start from (in OOP terms to "extend" from) and only change the parts i need... More on that later. Here is the boilerplate module with some debugging info to illustrate the internal flow on the tracy console: See the module in action in the tracy console ( @adrian has done such an amazing job with that module!!!): The code should be self-explaining. What is interesting, though, is that after the ### getUnformatted ### dump there is only one call to "___formatValue". All the other calls (loadPageField, wakeupValue and sanitizeValue) are not executed because the value is already stored in memory. Only the formatting part was not done at that point. With that concept it is very easy to create your very own custom Fieldtypes: <?php namespace ProcessWire; /** * Demo Fieldtype Extending the Boilerplate Runtime Fieldtype * * @author Bernhard Baumrock, 03.10.2018 * @license Licensed under MIT * @link https://www.baumrock.com */ class FieldtypeDemo extends FieldtypeMarkup { public static function getModuleInfo() { return [ 'title' => 'Demo', 'version' => '0.0.1', 'summary' => 'Demo Fieldtype', 'icon' => 'code', ]; } /** * convert the wakeupValue to the given format * eg: convert a page object to a string */ public function ___formatValue(Page $page, Field $field, $value) { $value = parent::___formatValue($page, $field, $value) . " - but even better!"; d($value, '___formatValue --> convert to whatever format you need'); return $value; } } Notice the change "but even better" in the last two dumps. I think it can't get any easier, can it?! ? I'll continue testing and improving this module, so any comments are welcome! 2. A Fieldtype that stores information in the database See this module for an easy example of how to extend FieldtypeText:
    1 point
  18. Hi, So today I will writing a small tutorial on developing templates in Processwire using Twig Template, Processwire is a highly flexible CMS which gives developers/designers/users options and allows easy extension of the platform. So here goes the tutorial What is Twig Template ? Simply put in my own words, Twig is a modern templating engine that compiles down to PHP code, unlike PHP, Twig is clean on the eyes , flexible and also quite *easy* to have dynamic layout site with ease ,without pulling your hair out. Twig is trusted by various platforms. It was created by the guys behind Symfony. Take this code as an example {% for user in users %} <h1>* {{ user }}</h1> {% endfor %} This will simply be the equivalent in PHP World <?php $userArray = ["Nigeria","Russia"]; foreach($userArray as $user): ?> <h1><?= $user ?></h1> <?php endforeach; The PHP code though looks simple enough however, you start to notice that you have to be concerned about the PHP tags by ensuring they are closed properly , most times projects gets bigger and comes complex and harder to read/grasp, and also in PHP you can explicitly create variables in the template making it very hard to read as it grows and prone to getting messy WordPress is a major culprit when it comes to that regard. Have you ever wanted to created separate layouts for different pages and break your sites into different parts e.g Sidebar, Comment Section, Header Section ? the regular approach would be to create individual pages for each section and simply add them as templates for the pages and with time, you can end up having tons of templates, however Twig allows you to easily inherit templates and also override the templates where you can inject content into the block easily. Don't worry if you don't understand the concept, the following parts will explain with an example of how to easily inherit layouts and templates. Layout <!DOCTYPE html> <html lang="en"> <head> {{include("layout/elements/header.twig")}} </head> <body> <div class="container-fluid" id="minimal"> <header id="pageIntro"> <div class="bio_panel"> <div class="bio_section col-md-6"> <h1>Okeowo Aderemi</h1> <h2>{{ page.body }}</h2> </div> </div> <div class="clearfix"></div> </header> <section id="page-body"> <div class="container"> <div id="intro" class="col-md-7 col-lg-7"> <h1>About me</h1> <h2> {{ page.summary }} </h2> </div> {block name="content"}{/block} <a style="font-size:1.799783em; font-style:italic;color:#d29c23" href="{{pages.get('/notes').url }}">Read more articles</a> </div> <div class="clearfix"></div> </div> </section> </div> <footer> <div class="header-container headroom headroom--not-top headroom--pinned" id="header-container"> {{include("layout/elements/footer.twig")}} </div> </footer> </body> </html> This is basically a layout where we specify blocks and include other templates for the page, don't panic if you don't understand what is going on, I will simply break down the weird part as follows: Include This basically is similar to native PHP 'include', as it's name suggests it simply includes the templates and injects the content into the layout , nothing out of the ordinary here if you are already familiar with php's include function. {{ output }} This simply evaluates the expression and prints the value, this evaluate expressions, functions that return contents , in my own short words it's basically the same as <?= output ?> except for the fact that it's cleaner to read. {% expression %} unlike the previous this executes statements such as for loops and other Twig statements. {% for characters in attack_on_titans %} <h1> {{characters}} </h1> {% endfor %} This executes a for loop and within the for loop, it creates a context to which variables in that context can be referenced and evaluated, unlike dealing with the opening and closing PHP tags, Twig simply blends in with markup and makes it really quick to read. I will simply post the contents of both the header and footer so you can see the content of what is included in the layout header.php <meta charset="utf-8"/> <meta content="IE=edge" http-equiv="X-UA-Compatible"/> <meta content="width=device-width, initial-scale=1" name="viewport"/> <title> {{ page.title }} </title> <link href=" {{config.urls.templates }}assets/css/bootstrap.min.css" rel="stylesheet"/> <link href="{{config.urls.templates }}assets/css/main.min.css" rel="stylesheet"/> <link rel='stylesheet' type='text/css' href='{{config.urls.FieldtypeComments}}comments.css' /> <link rel="stylesheet" href="{{config.urls.siteModules}}InputfieldCKEditor/plugins/codesnippet/lib/highlight/styles/vs.css"> <script type="text/javascript" src="{{config.urls.siteModules}}InputfieldCKEditor/plugins/codesnippet/lib/highlight/highlight.pack.js"></script> <script src="{{config.urls.templates }}assets/js/vendors/jquery-1.11.3.min.js"> </script> <script src="{{config.urls.templates }}assets/js/vendors/bootstrap.min.js"> </script> <script src="{{config.urls.FieldtypeComments}}comments.js"></script> <link rel="stylesheet" type='text/css' href="{{config.urls.templates}}js/jquery.fancybox.min.css"> <script src="{{config.urls.templates}}js/jquery.fancybox.min.js"></script> {block name="javascriptcodes"}{/block} footer.php <nav class="site-nav pull-right"> <div class="trigger"> <a class="page-link" href="{{pages.get('/about').url}}"> <span>{</span> About <span>}</span> </a> <a class="page-link" href="{{pages.get('/notes').url}}"> <span>{</span> Journals <span>}</span> </a> <a class="page-link" target="_blank" href="https://ng.linkedin.com/in/okeowo-aderemi-82b75730"> <span>{</span> Linkedin <span>}</span> </a> <a class="twitter page-link" target="_blank" href="https://twitter.com/qtguru"> <span>{</span> Twitter <span>}</span> </a> </div> </nav> There's nothing special here, other than twig simply injecting these fragments into the main layout , the next part is the most interesting and important concept and benefit that Twig has to offer {% block content %}{% endblock %} This tag simply creates a placeholder in which the content would be provided by the template inheriting this layout, in lay terms it simply means child templates will provide content for that block, the 'content' simply uses the name 'content' to refer to that specific block, so assuming we were to inherit this template it would simply look like this. Inheriting Template Layout {% extends 'layout/blog.twig' %} {% block content %} <div class="container blog-container"> <section class="blog"> <header class="blog-header"> <h1> {{page.title}} </h1> <h5 class="blog_date"> {{page.published|date("F d, Y")}} </h5> <br> </br> </header> <div class="blog_content"> <hr class="small" /> {{page.body}} <hr class="small" /> </div> </section> </div> {% endblock %} {% block nav %} <div class="col-md-4 col-xs-4 col-sm-4 prev-nav"> <a href="{{page.prev.url}}"> ← Prev </a> </div> <div class="col-md-4 col-xs-4 col-sm-4 home-nav"> <a href="{{homepage.url}}"> Home </a> </div> <div class="col-md-4 col-xs-4 col-sm-4 next-nav"> <a href="{{page.next.url}}"> Next → </a> </div> {% endblock %} In this snippet you can easily notice how each blocks previously created in the header and layout are simply referenced by their names, by now you will notice that twig doesn't care how you arrange the order of each block, all Twig does is to get the contents for each blocks in the child templates and inject them in the layout theme, this allows flexible templating and also extending other layouts with ease. Twig in Processwire Thanks to @Wanze we have a Twig Module for Processwire and it's currently what i use to build PW solutions to clients https://modules.processwire.com/modules/template-engine-twig/ The Modules makes it easy to not only use Twig in PW but also specify folders to which it reads the twig templates, and also injects Processwire objects into it, which is why i can easily make reference to the Pages object, another useful feature in this module is that you can use your existing template files to serve as the data provider which will supply the data to be used for twig template. take for example, assuming I wanted the homepage to display the top six blog posts on it, TemplateEngineTwig will simply load the home.php ( Depending on what you set as the template), it is also important that your twig file bears the same name as your template name e.g home.php will render into home.twig here is an example to further explain my point. home.php <?php //Get the Top 6 Blog Posts $found=$pages->find("limit=6,include=hidden,template=blog-post,sort=-blog_date"); $view->set("posts",$found); The $view variable is the TemplateEngine which in this case would be Twig, the set method simply creates a variables posts which holds the data of the blog posts, the method allows our template 'blog.twig' to simply reference the 'posts' variable in Twig Context. Here is the content of the 'blog.twig' template blog.tpl {% extends 'layout/blog.twig' %} {% block content %} <div class="block_articles col-md-5 col-lg-5"> {% for post in posts %} <div class="article_listing"> <span class="article_date"> {{post.published}}</span> <h2 class="article_title"> <a href="{{post.url}}">{{post.title}}</a> </h2> </div> {% endfor %} {% endblock %} So home.php sets the data to be used in home.tpl once Twig processes the templates and generates the output, twig takes the output from the block and injects it in the appriopriate block in the layout, this makes Processwire templating more flexible and fun to work with. The major advantage this has; is that you can easily inherit layouts and provide contents for them with ease, without the need of running into confusions when handling complex layout issues,an example could be providing an administrator dashboard for users on the template side without allowing users into the Processwire back-end. You can also come up with several layouts and reusable templates. Feel free to ask questions and any concerns in this approach or any errors I might have made or overlooked. Thanks
    1 point
  19. It would be handy to automate import and export of fields across installations. The reference for this is the wp ACF json functionality, which in practice allows checking field changes into version control and syncing field config updates without having to worry about the database. This would be achieved by automatically creating json export files when saving a field, checking these json files for changes in the fields list, and providing ui to import the changes if wanted. It seems like a module could easily manage this using available hooks, but just wondering if others would find this handy or if it is on any sort of roadmap. Sorry if I am doubling up on this, there is lots of talk around different modules like Migrations but nothing specifically about automating current field import / export functionality.
    1 point
  20. I use curly braces, like this: {$page->title}-[Y_m_d_H_i_s]
    1 point
  21. @bernhard I've not much time to work on my OSS stuff at the moment, as I'm no longer actively using it in my everyday work. But I'd happy to collaborate if someone wants to make a companion module and make sure the needed functionality is callable on the module.
    1 point
  22. Have you tried to export as ZIP with a current pw version? 3.0.119 ?
    1 point
  23. Hi Mikie, the need is definitely there but I think Migrations is the best option already. See the blog post here: https://processwire.com/blog/posts/introduction-migrations-module/ There's also some discussion about that here: See especially my comment regarding automating PW's internal import/export featurs and the problems you might get: And also see the comments by Benjamin at the very end of his blog post.
    1 point
  24. @szabesz thanks for info! AdminOnStroids seems a bit oversized for just adding a CKEditor plugin? simply too mighty for what I need... ?
    1 point
  25. I asked my hosting company to install the timezone tables and they said it's not possible on shared server and changing manually the offset is bad but then I found about the capital "I" on date format where we can easily detect if the DST changes. So here is the best solution: if (date('I', time())) { $config->dbInitCommand = "SET NAMES '{charset}', time_zone = '+03:00' "; } else { $config->dbInitCommand = "SET NAMES '{charset}', time_zone = '+02:00' "; }
    1 point
  26. Thanks. Effectively working, I messed up titles of fields. Feel a little bit noob... ?
    1 point
  27. Hello @Gadgetto The easiest way to add Codemirror is by using AdminOnSteroid module, see: https://github.com/rolandtoth/AdminOnSteroids/wiki/CKEaddons Beside a one click install, you can also configure loads of other things to your liking ?
    1 point
  28. Thanks @kongondo, you are one of the first to say something positive! Had only critics so far (probably fair) ... ? Already thought that with my basic knowledge it was a bit too early to write a tutorial. It was more a lesson for myself because I searched the forum on how to implement a language switcher for front-end. The clues I found were all a little unclear and incomplete. Especially the hints about getting the correct ISO code using php conditions although we have the wonderful custom fields to our disposal were not exactly satisfying.
    1 point
  29. @bernhard would you mind editing WireFileTools.php and in rmdir() method insert $path = rtrim($path, "/"); just before $files = scandir($path);
    1 point
  30. I have not used this one before, but there is a plugin called codemirror plugin that should accomplish what you need: https://ckeditor.com/cke4/addon/codemirror Drats, dragan just beat me to it..
    1 point
  31. you could try a CKE plugin like https://ckeditor.com/cke4/addon/codemirror
    1 point
  32. That's strange. At 23 posts you should really be able to edit your posts. A recent upgrade probably messed things up or your account got messed up in some way. Anyway, @horst is looking into it. Thanks for your enthusiasm for ProcessWire and your willingness to share your experience at this early stage ?.
    1 point
  33. @Gadgetto I wanted to say the same as @bernhard said, but he was quicker. Flags are no indicator for languages but indicate countries instead. This is something I constantly tell my customers, that want to have multi-language sites. For a good implementation of a language switcher take a look at https://www.p-jentschura.com There I follow best practices for a language switcher.
    1 point
  34. Thx for the tutorial! You might re-think the approach of using flags for your language switcher. See http://www.flagsarenotlanguages.com/blog/ and http://www.flagsarenotlanguages.com/blog/why-flags-do-not-represent-language/ for example. Or this one: https://wplang.org/never-use-flags-language-selection/ Actually this comment proves the problem with flags... for me the comment sounded weird at first sight (because reading "my" flag as "wrong" felt strange ? ), but actually that's exactly the problem with flags and it might be better to have a text-only version. IMHO adding a language switcher is still too much hazzle... Maybe I'll build a small module for that as I'm building a multilang site right now anyhow. Or are there already solutions?
    1 point
  35. Hi @Gadgetto, if you don't have edit links in your posts, it may be a limitation for new forum users, that will go away after a number of posts. Not really sure so. If I will find out more, I come back here or PM you.
    1 point
  36. https://processwire.com/talk/topic/13196-adding-image-field-to-language/ containing a link to http://daily.unitedlanguagegroup.com/stories/editorials/inside-design-language-selector-no-flags https://processwire.com/talk/topic/16524-extending-languages-template/ containing a link to http://www.flagsarenotlanguages.com/blog/why-flags-do-not-represent-language/ https://processwire.com/talk/topic/14241-language-names-and-utf8-page-names/ Please take these concerns earnest.
    1 point
  37. Hi Gadgetto, two remarks: (1) Your very first animated GIF shows the wrong flag for Germany: It's the flag of Austria - a German speaking country, that's true. This is a great example for the following insight: (2) It is not the right way to distinguish languages by flags! There are some threads here in the forum where this question is discussed. When I find some link, I'll share it.
    1 point
  38. Here is the GitHub link to the flag-icon-css repo: https://github.com/lipis/flag-icon-css Don't use flags for language selectors as flags do not represent languages!
    1 point
  39. I have this same problem. Has anyone found a solution?
    1 point
  40. It's really just adding the field to the finder:
    1 point
  41. This looks awesome! I was considering a similar advanced DateTime module that would store the UTC offset in addition to the timestamp, so in the UI you could select the date, time, and timezone. I might try this out and see if I can extend it for that purpose.
    1 point
  42. That book is GOLD, its content made such an impression on me that I also instantly took that advice and never listen to music again when coding/designing/drawing. It's the closest I have to a Bible.
    1 point
  43. So, this isn't my favourite Music, but it is Music. At archiche.org you can download / listen to 25k+ 78rpm recordings like this one: https://archive.org/details/78_bugle-call-rag_metronome-all-star-band-pettis-meyers-schoebel-t.-mondello-b.-carter_gbia0011087a/Bugle+Call+Rag+-+Metronome+All+Star+Band.flac
    1 point
×
×
  • Create New...