Leaderboard
Popular Content
Showing content with the highest reputation on 01/12/2018 in all areas
-
In this post, we take a look at all that was covered in 2017, and our roadmap for 2018, which includes plans for the year ahead. https://processwire.com/blog/posts/processwire-2018-roadmap/10 points
-
Hi @cosmicsafari Just look in the cache directory for a file called LazyCronLock.cache. If it is there for more than half a minute (or however long you estimate your code should run for) then delete it to unjam LazyCron. If this keeps happening, then there could be something in your hook method that is timing out and leaving the lock file there. Here's some code to return the location of the file if you want to do it programmatically... function getLazyCronLockfileName() { return wire('config')->paths->cache . "LazyCronLock.cache"; }4 points
-
I usually go by @rafaoski's approach. I first go to http://www.favicomatic.com/, upload a 500x500 image to generate a full icon pack. Then I place the icons in their own folder inside the templates folder. Usually /site/templates/img/favicon/ Favicomatic gives you a rather large HTML snippet. Slap that on your template, and on each line that points to a file, you'll have to fix the url, like so: <link rel="icon" type="image/x-icon" href="<?= $config->urls->templates ?>img/favicon/favicon.ico">3 points
-
I've been working with FieldtypeOptions recently and in the absence of documentation thought I would share some example code: $field = $fields->get('test_options'); /* @var FieldtypeOptions $fieldtype */ $fieldtype = $field->type; // Get existing options // $options is a SelectableOptionsArray (WireArray) // If there are no options yet this will return an empty SelectableOptionsArray $options = $fieldtype->getOptions($field); // Create an option $yellow = new SelectableOption(); $yellow->title = 'Yellow'; $yellow->value = 'yel'; // if you want a different value from the title // Don't set an ID for new options - this is added automatically // Will deal with 'sort' property later // Create another option $orange = new SelectableOption(); $orange->title = 'Orange'; // Add option after the existing options $options->add($yellow); // Get an option by title $green = $options->get('title=Green'); // Insert option at a certain position $options->insertAfter($orange, $green); // Remove an option $options->remove($green); // Reset sort properties (so order of options is the same as the SelectableOptionsArray order) $sort = 0; foreach($options as $option) { $option->sort = $sort; $sort++; } // Set options back to field $fieldtype->setOptions($field, $options);3 points
-
Password Generator Adds a password generator to InputfieldPassword. Usage Install the Password Generator module. Now any InputfieldPassword has a password generation feature. The settings for the generator are taken automatically from the settings* of the password field. *Settings not supported by the generator: Complexify: but generated passwords should still satisfy complexify settings in the recommended range. Banned words: but the generated passwords are random strings so actual words are unlikely to occur. https://modules.processwire.com/modules/password-generator/ https://github.com/Toutouwai/PasswordGenerator2 points
-
It sounds like one of the factors that determines which roadmap items get attention first is the level of interest within the community (makes sense). But it would be good to have a more accurate and transparent gauge of the interest in each roadmap item. A simple solution would be to have an official Roadmap sub-forum with a topic for each roadmap item (separate from the Wishlist sub-forum). The community could then indicate their interest in each item by "liking" it, and give feedback or ideas about implementation in topic replies. My vote for most desirable roadmap item: Add support for custom properties in file/image fields.2 points
-
Hi @SamC, One thing I find that helps me understand and better structure any classes I attempt to create is a UML tool. Personally, I learn best when I am shown how to do something and a UML diagram is the next best thing to having someone standing over my shoulder. If you are using PhpStorm, you can read about the UML feature here.2 points
-
I forgot about this .... everyone should upvote this to get a chance of being implemented. https://youtrack.jetbrains.com/issue/WI-36647 Or even better, any Java/PW gurus out there?1 point
-
@flydev, thanks for the report. Looks like I didn't account for use of InputfieldPassword without an associated FieldtypePassword. Fixed in v0.1.5 (I changed to semantic versioning).1 point
-
You could look at @kongondo's Blog Module http://modules.processwire.com/modules/process-blog/ for your News site and this thread may give you some ideas on how to cut down front end development time1 point
-
LazyCron is driven by user visits. Are you sure the site is being visited regularly? If you need to guarantee a run, you need to setup a cron job to visit a page on your site, or simply use cron itself to drive your tasks. Another possibility is that the cron script is timing out behind the scenes and leaving the LC script jammed.1 point
-
Check out this great module by @Robin S http://modules.processwire.com/modules/custom-inputfield-dependencies/1 point
-
1 point
-
There are loads of favicon generators. I generally use https://www.favicon-generator.org/ then point the link href to the appropriate directory & file1 point
-
Hi @Robin S In a process module I am writing, there is a function to create a new user. With PasswordGenerator installed (a must have!) I get the following notice : PHP Notice: Trying to get property of non-object in .../modules/PasswordGenerator/PasswordGenerator.module:76 When I dump $field, Tracy return a null value : $field = $inputfield->hasField; // line 47 There is nothing special in the function, I just declare a new InputfieldPassword : [...] // password $field = new InputfieldPassword(); $field->attr("id+name","password"); $field->label = __("Mot de passe"); $field->required = true; $field->minlength = 6; $field->columnWidth = 50; $form->append($field); [...] $out = $form->render(); return $out; Thanks.1 point
-
A quick tutorial how to create file downloads using pages You will be able to create a new page using template "PDF" (or any you setup), upload a pdf file. You then can select this page using page fields, or links in Wysiwyg. The url will be to the page and NOT the file itself. This will allow to keep a readable permanent unique url (as you define it), unlike /site/assets/files/1239/download-1.pdf, and you'll be able to update/replace the uploaded file without worring about its filename. Further more the file will also have an id, the one of the page where it lives. Clicking those links will download or open the file (when target="_blank") like it would be a real file on server with a path like /downloads/project/yourfile.pdf. You'll be also able to use the "view" action directly in the page list tree to view the file. Further more you'll be able to esaily track downloads simply by adding a counter integer field to the template and increase it every time the page is viewed. Since the file is basicly a page. This all works very well and requires only minimal setup, no modules and best of it it works in the same way for multi-language fields: Just create the language alternative fields like "pdf, pdf_de, pdf_es" and it will work without modifying any code! Still with me? ok PW setup Download folder: Create a template "folder" or "download-folder" with only a title needed. Create pages in the root like /downloads/project/ using this template. Setup the template for the pdf files 1. Create a new template in PW. Name it pdf 2. Goto template -> URLs tab and set the URL end with slash to no. (So we can have /path/myfile.pdf as the URL) 3. Create a new custom file field, name it pdf. Set its maximal count to 1 under -> Details tab. 4. Add the pdf field created to the pdf template. Easy. 5. Create a new "pdf" page using the pdf template under a download folder you created earlier. 6. Give it the title and in the name field add ".pdf" to the end (could also leave as is) Template PHP file for the pdf files 1. Create the template file pdf.php in your /site/templates folder 2. add the following code: <?php // pdf.php if($page->pdf){ wireSendFile($page->pdf->filename); } Done. To see the options you have with PW's wireSendFile() you can also overwrite defaults <?php // pdf.php if($page->pdf){ $options = array( // boolean: halt program execution after file send 'exit' => true, // boolean|null: whether file should force download (null=let content-type header decide) 'forceDownload' => false, // string: filename you want the download to show on the user's computer, or blank to use existing. 'downloadFilename' => '', ); wireSendFile($page->pdf->filename, $options); } Simple and powerful isn't it? Try it out. Some thoughts advanced Create as many file types as you like. It might also be possible to use one "filedownload" template that isn't restricted to one field type but evaluate it when being output using $page->file->ext, or save the file extension to the page name after uploading using a hook. One last thing. You can add other meta fields or preview images to the template and use those to create lists or detail pages. It's all open to goodness. Again all without "coding" and third-party modules. Further more you can use the excellent TemplateDecorator to add icons per template and have a nice pdf icon for those pages. This as a base one could also easily create a simple admin page for mass uploading files in a simple manner, and create the pages for the files automaticly. ImagesManager work in the same way. Cheers1 point
-
I'll look into them, thanks @rick Using visual studio code at the mo.1 point
-
The page export process should sort by the number of segments in the path to each page so that when you import they will be created in the correct order. At least that is how I handle it in Migrator: https://github.com/adrianbj/ProcessMigrator/blob/eaf8255aded36033bcd468c59b235b9a0eb6b785/ProcessMigrator.module#L379-L387 This sounds like a bug to report on Github.1 point
-
Just to give another opinion from @gmclelland , I organize the templates the following way: site/templates/fields/{name of the repeater matrix field}/{name of the rep. matrix type} e.g. Assuming a repeater matrix field called "content" with a type called "slider": site/templates/fields/content/slider.php So I rather end up with several files instead of rendering in the main template, one per matrix type. Then, on the template which has the repeater matrix field: content$page->render("content")1 point
-
$pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); if(!$page->id) return; // Page ID is 0 when page is first created // Your code here });1 point
-
For me it works fine. I think the issue is here. Because the index may be 0 this line should be: if (HotkeysSettings.indexOf('removeNoticeHotkey') !== -1) {1 point
-
I opened a feature request topic about this in the ProCache sub-forum (not sure if you have access to that). Will be interesting to see if Ryan will consider adding such a feature.1 point
-
ProcessWire will not allow you to POST to or call a script (PHP and such) directly if that script is located in one of its protected folders. Hence, the 403 (forbidden). Your options: Throw your script into a template file and post to a page using that template Throw your script into a module and post to that module's page (if backend; otherwise, will still get a 403) include/require once the script in some template file but post to a page using that template (e.g. posting to self as per @psy's suggestion) Etc... Ajax stuff:1 point
-
That's kind of you to say, thanks. Was on it for quite a few hours today. At the present time, it looks like this, but I wanted to be able to get more of the logic into the class, still seems a bit of a mess to me. <?php namespace ProcessWire; class FormChecker { // array to hold feedback messages public $feedback = []; // 3rd party validator object private $validator; public function __construct($validator) { $this->validator = $validator; } public function checkForm() { return $this->validator->validate(); } public function checkField($name) { return $this->validator->errors($name); } public function displayFeedback() { $str = ""; if (count($this->feedback)) { $str = '<ul class="mb-0">'; foreach ($this->feedback as $value) { $str .= '<li>' . $value . '</li>'; } $str .= '<ul>'; } return $str; } } // require Valitron class require_once("./vendor/vlucas/valitron/src/Valitron/Validator.php"); // get recaptcha module $captcha = $modules->get("MarkupGoogleRecaptcha"); // get sanitized variables $name = $sanitizer->text($input->post->name); $email = $sanitizer->email($input->post->email); $message = $sanitizer->textarea($input->post->message); // create new valitron $v = new \Valitron\Validator(array( "name" => $name, "email" => $email, "message" => $message ) ); // create valitron rules $v->rule("required", ["name", "email", "message"]); $v->rule("email", "email"); // save as property on new $checker object $checker = new FormChecker($v); // has form been submitted? $isSubmitted = $input->post->sendMe; // default mail sent value $isSent = false; if ($isSubmitted) { // does form validate after submission $formValidates = $checker->checkForm(); // recaptcha result $recaptcha = $captcha->verifyResponse(); if (!$recaptcha) { array_push($checker->feedback, "Recaptcha must be complete."); } if (!$formValidates) { array_push($checker->feedback, "Please fill out the fields correctly."); } if ($recaptcha && $formValidates) { $msg = " <html> <body> <p><b>Name:</b> {$name}</p> <p><b>Email:</b> {$email}</p> <p><b>Message:</b></p> <p>{$message}</p> </body> </html>"; $mail = wireMail(); $mail->to("sam@woodenfoxdesign.com") ->from($email, $name) ->subject('Email from website...') ->bodyHTML($message); $isSent = $mail->send(); if ($isSent) { array_push($checker->feedback, "Thanks for your message!"); } else { array_push($checker->feedback, "Sorry, an error occured. Please try again."); } } } ?> <div id="form-top"></div> <h2>Suggest a tutorial</h2> <?php if($isSubmitted):?> <div class="alert <?= ($isSent) ? 'alert-success' : 'alert-danger'?>" role="alert"> <?= $checker->displayFeedback(); ?> </div> <?php endif;?> <form id="contact-form" method="post" action="#form-top"> <div class="row"> <div class="form-group col-sm-12 col-lg-6 py-2 <?= $checker->checkField('name') ? 'has-danger' : ''?>"> <label for="name">Name (required)</label> <input class="form-control" name="name" id="name" type="text"> </div> <div class="form-group col-sm-12 col-lg-6 py-2 <?= $checker->checkField('email') ? 'has-danger' : ''?>"> <label for="email">Email (required)</label> <input class="form-control" name="email" id="email" type="text"> </div> </div> <div class="form-group py-2 <?= $checker->checkField('message') ? 'has-danger' : ''?>"> <label for="message">Message (required)</label> <textarea class="form-control" name="message" id="message" rows="8"></textarea> </div> <div> <label for="recaptcha">Recaptcha (required)</label> <!-- Google Recaptcha code START --> <?php echo $captcha->render(); ?> <!-- Google Recaptcha code END --> </div> <div class="form-group"> <button type="submit" class="btn btn-primary mt-3" name="sendMe" value="1">Suggest tutorial <i class="fa fa-angle-right" aria-hidden="true"></i></button> </div> </form> <?php echo $captcha->getScript(); ?> I think I'll have another crack over the weekend, I've learned a few new things about classes so that's good. My brain hurts.1 point
-
Hard to tell without seeing the script. Are you sure the script is being loaded at all? Your options (some of which you have tried) Call it in a template file (include or require once). Create a page using the template and POST to that page or if it is a form on the page, POST to self Create a module based on the script. Call the module Create a module whose purpose is to call the script (include or require once) Trying to access the script directly from protected ProcessWire folders will not work, e.g. /site/templates/myscript.php. Could it be a namespace issue? Have you tried to Debug? Tracy?1 point
-
This code should help you get to the wire directory: <link rel="icon" type="image/x-icon" href="<?php echo $config->urls->root ?>wire/favicon.ico"> But I prefer to add in the directory of my template files in which I change the path to (templates/): <link rel="icon" type="image/x-icon" href="<?php echo $config->urls->templates ?>assets/img/favicon.ico"> Here you can read more about $config: https://processwire.com/api/variables/config/1 point
-
Hi y'all! Long time no see. Here's a little module aiming to help you build accessible websites ProcessWire Accessibility Tools Download: http://modules.processwire.com/modules/pwat/ Github: https://github.com/marcus-herrmann/PWAT A small, but hopefully growing toolkit for creating accessible ProcessWire sites. Right now it consists of the following little helpers: tota11y visualization toolkit by Khan Academy A toggle button to see view site in grayscale. The w3c recommends checking your page without colours to see if your design still works (accompanied by a colours contrast check, which is part of tota11y) A link to test your webpage with WAVE, webaim's Web Accessibility eValuation Tool. By the nature of this tool, the website under test must be available online, local hosts won't work. Installation Once you have downloaded PWAT, go to your module Install page and click "Check for new modules". Find "ProcessWire Accessibility Tools" and click "Install". During installation, PWAT creates a new role 'pwat_user'. To use the Accessibility Tools, you have to grant user this role. Following, you can start configuring the module. Usage PWAT starts with only the tota11y script activated. On the configuration page you can decide whether PWAT is visible on admin pages if tota11y is active if the grayscale toggle is active if the link to WAVE will be visible Credits The amazing tota11y visualization tool by Khan Academy Inspiration: Paul J. Adam's bookmarklets Inspiration: WordPress wa11y Plugin Best, marcus1 point
-
Welcome to the forums @mikhail $page->find() could be useful here. I think something like this should do the trick: // This category plus all child categories under it $categories = $page->find()->prepend($page); $pano_results = $pages->find("location_category=$categories, sort=-shoot_date, limit=10");1 point
-
I chucked up a tutorial here: https://www.pwtuts.com/processwire-tutorials/making-a-custom-admin-theme-using-uikit-3-and-the-included-build-tools/ Hoping this method will become redundant though if I can get my head round building a module to change the colours etc. Something to work on in January (without distracting me from my JS which I should be doing...).1 point
-
Thanks @abdus Relating to the topic, there are other code snippets lurking in the Forum, like: Have a different title of a field across multiple templates? Hook to hide inputfield in Admin Custom Field in Page SettingsTab Remove a fieldset tab from specific pages of a template1 point
-
Sure, this is done in v0.0.2 If you know of a Javascript library that can generate those sorts of passwords while still satisfying password field settings I'd be happy to integrate it. But I think memorising passwords is only a short hop away from reusing passwords, which is asking for trouble.1 point
-
Here's a short snippet for site/ready.php that hooks after ProcessPageEdit::buildForm and moves a regular field (named "testfield here") from the Content tab to Settings. The methods used are from the InputfieldWrapper class. <?php wire()->addHookAfter("ProcessPageEdit::buildForm", null, "moveFieldToSettings"); function moveFieldToSettings(HookEvent $event) { $form = $event->return; $field = $form->find("name=testfield")->first(); if($field) { $settings = $form->find("id=ProcessPageEditSettings")->first(); // Alternatively, find a specific field to insert before/after: // $settings = $form->find("name=template")->first(); if($settings) { $form->remove($field); $settings->append($field); // In the alternative, insert before or after the found field: // $form->insertBefore($field, $settings); } } }1 point
-
I have never liked the principle of using ID's that way. And I will never use it this way unless i'm absolute sure that the page can't be deleted or the ID is fixed in the core (homepage / trash / admin etc.). The problem with ID's is that when you delete the page, your ID is gone and your script will break. And a minor thing with ID's is that the ID wil not tell you anything about the page, so you need to comment it. I think it's almost always better to get a page from it context. Context of a page can be the template, the position of the page relative to an other, the amount of parents or kind of children. Or maybe even a combination of those factors. When you program with 'context' your client wil never be able to break your site.1 point
-
I have a model field that depends on the selected manufacturer. Its options update upon manufacturer selection (both are page select fields). In my model field > Input tab > Selectable Pages > Custom selector, I have: parent=page.make, template=model, sort=title, include=all Where 'make' is the name of my manufacturer field. Try that?1 point