Leaderboard
Popular Content
Showing content with the highest reputation on 09/11/2016 in all areas
-
@ryan It might be useful to update the module documentation regarding your latest release (2.0.8) from... <script type='text/javascript' src='https://maps.googleapis.com/maps/api/js?sensor=false'></script> to something like... <script type='text/javascript' src='https://maps.googleapis.com/maps/api/js?key=<?=$modules->FieldtypeMapMarker->googleApiKey?>'></script> ...in order for the frontend to also use the API key when rendering a map.3 points
-
You should be able to get the page from this: $page = $event->object->getPage(); But the other thing to consider is that I think what you are trying to do is already support by a core permission. Try installing that "page-edit-created" permission. It may not be as flexible, but worth point out in case you didn't know about it. The other thing is that you don't need a full module for small snippets like this - you can place the code in /site/init.php instead.2 points
-
2 points
-
I don't believe it has been explored for maybe the following reasons: (1) I would look first at the stated requirements for ProcessWire https://processwire.com/about/requirements/ It should be noted that it says that MySQL is required (or any MySQL compatible database i.e. MariaDB) (2) Furthermore, I don't believe anyone has explicitly said that it technically can't be done, however you first need a good understanding of the differences between MySQL and SQL Server (MSSQL). Then you would need to account for these differences in your code. http://www.databasejournal.com/features/mysql/mapping-data-types-between-mysql-and-sql-server.html http://www.databasejournal.com/features/mysql/comparing-sql-server-and-mysql-functions.html (3) Additional vital information regarding Microsoft Infrastructure (Database technology), in case you want to pursue getting this to work https://www.microsoft.com/en-us/download/details.aspx?id=20098 http://www.iis.net/learn/application-frameworks/install-and-configure-php-on-iis/install-the-sql-server-driver-for-php (4) Additional information regarding Microsoft Infrastructure (Web Server technology) which will always be applicable when working with Windows solutions http://www.iis.net/ There is much information (provided before) about using Microsoft technologies (specifically IIS working with MySQL) to enable working with ProcessWire. They work without changing coding standards and I believe many people are using these solutions successfully. BTW, .Net is a Microsoft technology and framework2 points
-
2 points
-
It's probably as simple as temporarily disabling this language inheritance for each field only for the request, where you're building the list. foreach($multiLangField as $f) { $f->langBlankInherit = LanguagesPageFieldValue::langBlankInheritNone; } // Check all your fields // Make sure non of the fields is saved before exiting2 points
-
That's true, but that's really not a problem. There are people with millions of pages in their processwire installation, so even ~1000 pages for seo field won't matter and that's already a big website. Ryan did already "kinda" mark this path as the way to go as he did develop the repeater field the same way, with it also potentially holding a lot of small pages even for only 2 to 3 fields. There's just no need to introduce new systems into the core, when everything needed is already possible. Contrary to the raw data-model implementation the field can certainly be refined in terms of handling in the backend UI, so for example that group subfields are populated to the template fields and are kinda marked as group. But that are mostly UI conveniences. Like I said in the other wishlist topic: Nobody does need to necessarily know that those grouped fields are saved in separate pages.2 points
-
Ownership appears to be user geot and group geot. Apache normally runs under another user account like 'apache' or 'http'. If you change ownership of config.php to the apache user, you won't need to use the insecure settings allowing anyone to modify the file. By the way, using chmod 006 doesn't make a lot of sense, you're saying the owner and group of the file won't have access, only some other user.2 points
-
Updated to v062 with the following changes: support for inline CKE fields (CKEaddons) fix LightWire skin missing context menu icons (CKEaddons) added 'Find' and 'Maximize' plugins for CKEaddons added 'Set wider main content' for (default) AdminTweaks submodule options 2 columns layout for default theme above 1479px screen width fix missing pagelist icon set in template (PageListThumbs) several fixes for truncated long page titles timestamp for main module CSS and JavaScript file to prevent caching issues I wasn't able to duplicate @ceberlin's issue. Are you sure you don't have other custom config.js loaded? AOS sets the path for each CKE field's config.js to the AOS directory, so if you enter this to the console you should see a path to AOS (replace "body" with your field's name): ProcessWire.config.InputfieldCKEditor_body.customConfig -> "/site/modules/AdminOnSteroids/CKE/config.js" Currently the regular and inline CKEditors are handled differently in AOS because inline editors behave differently. I'll see if this could be improved.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
-
Simple Contact Form Using Google Recaptcha & Valitron validation library I just finished creating a simple Contact-Form for a client's website so i thought it would be really helpfull to share it with the community. The contact form uses: Google recaptcha for validating the user is not a robot (https://github.com/google/recaptcha) Valitron validation library for validating the form fields (https://github.com/vlucas/valitron) Twitter Bootstrap 3.0.0 for form HTML The contact-form is located inside a contact-page, so the bare minimum you need in order to setup your own is: contact.php (template file used by your contact-page) _contact-controller.php (file used as a controller for your contact-form functionality like send email, validate fields etc) 2 extra lines inside your composer.json file So, let's start: First you need to update your composer.json file adding 2 lines inside the require object: "vlucas/valitron": "^1.2", "google/recaptcha": "~1.1" Here is a sample composer.json file: { "name": "processwire/processwire", "type": "library", "description": "ProcessWire CMS/CMF", "keywords": [ "cms","cmf", "content management system" ], "homepage": "https://processwire.com", "authors": [ { "name": "Ryan Cramer", "email": "ryan@processwire.com", "homepage": "https://processwire.com", "role": "Developer" } ], "require": { "php": ">=5.3.8", "ext-gd": "*", "vlucas/valitron": "^1.2", "google/recaptcha": "~1.1" }, "autoload": { "files": [ "wire/core/ProcessWire.php" ] }, "minimum-stability": "dev" } open console and navigate to processwire root folder (where composer.json file is) on this step i assume you have already setup composer for your project, otherwise google it run the following command: composer update this will create a vendor folder (if it does not already exist) and download valitron and google recaptcha libraries. Then open your contact-page template file(usually named contact.php inside your templates directory) and add the following: * Note: The form below uses bootstrap 3.0.0 css, so if you are using something else you need to make the appropriate changes. <?php namespace ProcessWire; include('_contact-controller.php') ?> <div class="container"> <div class="row"> <div class=" col-md-4"> <h2>Contact Form</h2> <?php if($session->flashMessage):?> <div class="alert <?=!$session->sent && (!$v->validate() || !$resp->isSuccess()) ? 'alert-danger' : 'alert-success'?>" role="alert"> <?php echo $session->flashMessage;?> </div> <?php endif;?> <form id="contact-form" method="post"> <div class="form-group <?=$v->errors('name') ? 'has-error' : ''?>"> <label for="name">Name</label> <input class="form-control" name="name" id="name" type="text" value="<?=$sanitizer->text($input->post->name)?>"> </div> <div class="form-group <?=$v->errors('email') ? 'has-error' : ''?>"> <label for="email">Email</label> <input class="form-control" name="email" id="email" type="text" value="<?=$sanitizer->text($input->post->email)?>"> </div> <div class="form-group <?=$v->errors('message') ? 'has-error' : ''?>"> <label for="message">Message</label> <textarea class="form-control" name="message" id="message"><?=$sanitizer->text($input->post->message)?></textarea> </div> <div class="form-group"> <!-- Google Recaptcha code START --> <div class="g-recaptcha" data-sitekey="<?=$googleSiteKey?>"></div> <script type="text/javascript" src="https://www.google.com/recaptcha/api.js"> </script> <!-- Google Recaptcha code END --> </div> <button type="submit" class="btn btn-primary">SEND</button> </form> </div> </div> </div> <?php //here we remove the flash-message because it is already shown above the form. $session->remove('flashMessage'); //reset 'sent' variable for future submit $session->sent = false; ?> Next create a file inside you templates directory with name: _contact-controller.php: and set the required variables($googleSiteKey, $contactFormRecipient, $contactPageID) <?php namespace ProcessWire; /** * here we include Valitron & Google recaptcha libraries * make sure the path is correct in your template */ include(dirname(__FILE__) . "/../../vendor/vlucas/valitron/src/Valitron/Validator.php"); include(dirname(__FILE__) . '/../../vendor/google/recaptcha/src/ReCaptcha/ReCaptcha.php'); /** * here we add the form field values to Valitron */ $v = new \Valitron\Validator(array( 'name' => $sanitizer->text($input->post->name), 'email' => $sanitizer->email($input->post->email), 'message' => $sanitizer->text($input->post->message), ) ); /** * validation rules set for each form field * For more details on Valitron/Validator usage visit: * https://github.com/vlucas/valitron */ $v->rule('required', ['name', 'email', 'message']); $v->rule('lengthMin', 'name', 5); $v->rule('email', 'email'); /** * set Google recaptcha site-key & secret-key * create a new key from: https://www.google.com/recaptcha/admin */ $googleSiteKey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; $googleSecretKey = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'; /** * set the email of the contact form recipient(usually the website owner) */ $contactFormRecipient = 'your@company.com'; /** * set the id of contact-page in order to redirect there when the form is sent */ $contactPageID = '1045'; //here we check whether the 'name' field exists inside post variables (which means the form is posted) if ($input->post->name) { //if fields validation passes if ($v->validate()) { $reCaptcha = new \ReCaptcha\ReCaptcha($googleSecretKey); $resp = $reCaptcha->verify($input->post->{'g-recaptcha-response'}, $_SERVER["REMOTE_ADDR"]); //if google-recaptcha validation passes if ($resp->isSuccess()) { //This is the HTML message $message = ' <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Contact Form | ' . $input->post->name . '</title> </head> <body> <p>' . $input->post->message . '</p> </body> </html>'; //here we send the form to $contactFormRecipient wireMail($contactFormRecipient, $input->post->email, "Contact Form | " . $input->post->name, $message); //here we set a flash-message to notify the user that the form was successfully sent $session->flashMessage = 'Thank you for your message! We will get in touch with you shortly.'; //save in session that the form is sent $session->sent = true; //finally redirect user to contact-page $session->redirect($pages->get($contactPageID)->url); } else { //self explain $session->flashMessage = 'Error while validating you are not a robot!'; } } } ?> Thats all! You now have a simple contact-form working with captcha and field validation! I would be more than happy to help anyone having problems on the setup.1 point
-
Trekkerweb Supply & Demand https://markt.trekkerweb.nl/ Trekkerweb.nl brings agricultural mechanization news and supply & demand together in a single online platform for all the tractor and machine enthusiasts and others interested in the mechanization sector. The site is multi-language with English as default. None Dutch browsers will get the English version of the site, currently we are finetuning the German version which will be available somewhere in the near future. The search page in English and Dutch language - https://markt.trekkerweb.nl/search/ - https://markt.trekkerweb.nl/nl/zoeken/ Used modules Profields Table Profields Textareas MarkupLoadRSS (fetches brand related new from the main website) PageImageManipulator 2 (PIM2) (for placing watermark image) ProCache ProcessGetVideoThumbs TextformatterVideoEmbed WireMailSmtp LanguageSupport (Site is multi language: Dutch, German and Default English) Couple of custom made modules for user profiles and cross page linkage of the datamodel (Bower) components awesome-bootstrap-checkbox bootstrap-dropdowns-enhancement-sass bootstrap-sass bootstrap-select font-awesome formvalidation.io hashids jquery jquery-file-upload jquery-throttle-debounce jquery.mmenu js-cookie lifestampjs moment semantic-ui-sass verge Front-end user profiles (custom module) Account registration Customizable fields (in module settings) Per field privacy configurable (private, public, on a per user basis). Front-end login/ logout Reset password Email activation for account Request activation mail View profile Public profile Edit profile Set profile picture (cover image and avatar) Modify password Language choice Profile dashboard Front-end Ads management Create new ad Edit existing ad Manage media (images / video) Preview and approve ad Remove ad Data model Categories Subcategories Brands Input fields Options An intuitive data model drives the whole site. A couple custom made modules take care of the cross page assigning of categories to subcategories and brands. Per subcategory we are able to assign the related input fields and options which will be rendered on the 'Create new ad/ Edit ad' form page and combined with the given values rendered on the ad detail page. Database caching + Pro caching One of the challenges was to keep the whole project as low weight as possible. Since the data model with categories, subcategories, brands, inputfields and options is the backbone of the site we came up with the solution to have the names, titles, ids, and relations between them cached. Completely as json/javascript with pro cache and separated with database caching. With the Wire Fuel we made the $dm object available for accessing anywhere in PHP and globalJS.dm from within javascript. This means the whole data model is called only once per request, and while it exists in the database cache and pro-cache it is incredibly fast. Subcategory page The first image shown below represent one of the subcategories (Tractors) with assigned categories, brands, input fields and options. The image there after is a screenshot of the add ad page, where the input fields, options and brands are dynamicly rendered after being loaded via Ajax. Other features cookie based favourites cookie based last-viewed list advanced filter search related ads Thanks to the whole team (Ferdi, Bastiaan, Alex, John, Hessel) and last but not least Ryan for creating ProcessWire and all module developers out there1 point
-
Warning: it's going to be TL;DR so proceed with caution In an effort to come up with an optimized development workflow, I have come up with the idea of implementing most of the required template files in the form of static HTML files first (based on a "CSS framework" which will also serve as the CSS base of the site). Basically I want to implement most of the frontend without touching ProcessWire in the first place. The advantage of this approach is that it is a lot faster to work with only HTML/CSS/JS during the frontend design phase of the project, and the end result of the design phase can be "similar" to a wireframe/mockup which can be presented to a client, but this "mockup" actually represents (say) 80% of the final design, so it is something that is rather good to work with when the backend development with ProcessWire begins. This also means that my ProcessWire template files will be mostly implemented with <?php echo ... ?> and alternative syntax control structures that can be "just injected" into the above mentioned static HTML template files to turn them into ProcessWire template files later on. So far so good, but my ProcessWire template files are going to be separated into "template file partials", and I also want to implement the static HTML template files in the same way, so that they are also separated into "template file partials", and ideally organized in the very same structure. E.g. I will include the site's navigation in the ProcessWire template file like this: <?php echo $navigation ?> So I want to do the same in the corresponding static HTML template file, something like this: <div data-template="partials_navigation"></div> If it can be done recursively, then I can implement the same in both cases. With ProcessWire, I use wireRenderFile() to render partials recursively, so I just had to figure out what to use in the case of the static HTML template files. What else to use if not JavaScript? I started off by googling around, looking for some pre-made solutions... I did not find too much that could help me, the only thing useful I could dig up is "HTML Imports", for example: http://blog.teamtreehouse.com/introduction-html-imports Note, that currently this technique only works in Chrome(-ium), but that is my choice in frontend development anyway. I've read somewhere that other browsers might never implement "HTML Imports", but that is to be seen... I have found a lot of articles explaining the basics of "HTML Imports", but I could not find any libraries or frameworks nor even something similar to what I need, so I implemented a proof of concept version of mine: I'm quite happy with the result so far. The JavaScript code needs some additional error handling, but otherwise it seems to do what I need. Here it is in action (Chrome(-ium) only!!!): [...no longer live...] And here is the source code for those who want to take a closer look: [...old stuff, I removed it to save space...] However, I'm pretty sure that someone must have already come up with this idea, so I'm asking the ProcessWire community if anyone can point me to similar solutions, something that I can study and/or use. So any piece of advice that might help me to take it to the next level, or any objections to this "HTML Imports" technique, any disadvantages? Thank you in advance1 point
-
You should probably take a look at this one: https://medium.com/webdevs/living-styleguide-mit-fractal-und-processwire-e900f05e0b79#.vij9p35p8 (I know I should translate it some time, but I heard it's quite readable with google translate)1 point
-
1 point
-
Well, at least I made a nifty (but not really useful) module @adrian About the screenshot: I did not know that I had to click on "add new" before I could see the "Install predefined system permissions" dropdown. (or should I say 'hidden panel')1 point
-
No - there is the list to install from - that's why I showed you that screenshot. That "Install predefined system permissions" is available from 2.7 onwards. Maybe even before, but it's definitely in the current stable as well as 2.8 and 3.x1 point
-
Permissions > Add New > Install predefined system permissions. Or you could just type out that permission name manually.1 point
-
1 point
-
1 point
-
@Robin S Of course, a dedicated solution to this problem would be welcome, however, limiting the number of repeater items has its own advantages too. A "limited repeater" can be a tool for more general issues, such as maximum number of slides in a slider, maximum number of widgets in a sidebar, etc... and in the meantime (i.e.: while we are waiting for the above described "grouped fields" ) implementing a limit for the number of repeater items seems to be a lot less work too. It is a valid hack to impose a limit of one item per repeater, and we can probably extend it so that it checks the number of repeater items and removes the button when the limit is reached, but this is still more of a hack than a straightforward solution. So I'm still for a core support for "limited repeaters"1 point
-
After a week of testing in 2.8 this appears resolved. I suspect a bug in 2.7 .3 thanks for the help1 point
-
While we're imagining how this group field might work, my two cents is that I don't think a limited repeater is the way to go. One likely use case for a group field is for SEO fields that would be added to nearly every template, so using a repeater-based group field would effectively double the number of pages in your site. I know that pages are designed to scale up nearly indefinitely but adding all these extra pages just seems unnecessary when there will only be one group field per page. The way I would like to see it is that the individual fields within the group are added directly to the template like normal fields are, but they would have a property that identifies them as belonging to a group. Having such a property would allow: The group field to appear in the template field list as a single item, so it's easy to move the grouped fields as one. Likewise it could be added to / removed from a template like a single field via the API. The group field settings would allow adding/removing/sorting fields to the group "pseudo-template" - as per a Repeater field, but a normal PW template would not be involved. This would require core changes of course, so would only happen if @ryan can see the value in having a group field in PW.1 point
-
no pick a template - the repeater field itself becomes the sub-fieldgroup ('template"); you probably just need to use ACF to do some CSS and JS adjustments to disable/hide the "add new item"1 point
-
1 point
-
This is by design. See this GitHub issue for more details. It's not the most consistent solution, but admittedly I've found it quite useful too.1 point
-
Has anyone tried to use this to connect PW to something like Zapier? I am trying to put aside some time to try it out, should work. nice work @clsource !1 point
-
Another approach, what works automatically everytime, and without additional support, (updating version numbers) can be: $timestamp = filemtime($config->paths->templates . 'scripts/myJsFile.js'); $myJsFile = $config->urls->templates . "scripts/myJsFile.js?ts={$timestamp}"; $config->scripts->add($myJsFile); I'm to lazy to add version numbers to all and everything. Also, last modified filetime is foolproof, not updated version number is not.1 point
-
Hi guys! I'm really happy to finally showcase this website in the forum. It's the website of a Porto based Digital Animation Studio. A bunch of talented folks, really. This is a heavily animated/scripted/ajaxed website, that makes use of CSS animations, transitions, transforms, HTML5 audio API, and so on and so on. I spent actually more time debugging than constructing it. Unfortunately, we didn't manage to kill all the bugs before the launching, so you might experience some along the way. We even had to give up on Safari (Damn buggy piece of software !!), and advice the user to use another modern browser. But we think it's still well worth it This is also the first website we developed but didn't design. The design is from the excellent The Royal Studio, from Porto. You might know some of their illustration work for the Adobe online tutorials. --- Enough talk, here is the link http://www.aimcreativestudios.com/ (No safari, please, you'll regret it) Hope you guys like it!1 point
-
See here how to paginate an existing array1 point
-
i.am first you can puut this in your head.inc tamplate or some includeded file before.u are doing $page->url $pages->addHookAfter('Page::path', null, 'hookPagePath'); function hookPagePath(HookEvent $e) { $page = $e->object; if($page->template == 'article') $e->return = "/blog/$page->name/"; }1 point