Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 11/05/2017 in all areas

  1. There are a number of problems here I think. $this->pages->addHookBefore('Inputfield::render', function($event) { You only use $this->pages to add a hook if you are hooking a method of the Pages class. You are hooking a method of the Inputfield class, so you want... $wire->addHookBefore('Inputfield::render', function($event) { Also, you don't need to hook every inputfield render. You are only interested in Checkbox inputfields so just hook the render method of that inputfield class. $wire->addHookBefore('InputfieldCheckbox::render', function($event) { $page = $event->arguments(0); Inputfield::render() and InputfieldCheckbox::render() take no arguments, so $page is not the first argument and you cannot get $page this way. $field = $event->object; The event object is an Inputfield object and not a Field object. It doesn't really matter what you name your variables, but to keep things clear in your head it might help to change this to: $inputfield = $event->object; if('createevents' === $field->name ){ <opinion>Yoda conditions make code less readable and more prone to misinterpretation. The disadvantages outweigh the benefits.</opinion> I would tend to write this hook as: $wire->addHookBefore('InputfieldCheckbox::render', function(HookEvent $event) { if($this->process != 'ProcessPageEdit') return; $page = $this->process->getPage();; $inputfield = $event->object; if(in_array($page->template->name, array('event_businessvacations', 'event_specialbusinesshours', 'event_dates', 'event_events'))) { if($inputfield->name === 'createevents' && !count($page->children)) { $inputfield->attr('disabled' , 'disabled'); } } }); Another tip is that when identifying an inputfield by name, it can be better to check the name of the associated field rather than the inputfield. This is because when an inputfield is inside a repeater its name includes a repeater suffix. Checking the associated field name works in all situations so I prefer that. if($inputfield->hasField == 'createevents' //... Note also the change to the == comparison operator. Not every inputfield has an associated field, so you couldn't be sure that hasField returns an object with the name property if you did: $inputfield->hasField->name === 'createevents' //...
    6 points
  2. Tomorrow! I need to go offline for today - my girlfriend is not so pleased if I am working to much on Sundays - Happy wife, happy life
    4 points
  3. This is my last an best working approach with no JS (only PHP). In this case I use a Hook with a regex and a session variable to add an additional option tag with "Please select" at the top. So the user has to select one of the template types. Otherwise he will get an error message. Only to mention: There is also another Hook used to create the notice at the bottom (but this is not part of this topic ) Here is the code, which should be placed inside ready.php: $wire->addHookAfter('InputfieldSelect::render', function(HookEvent $event) { if($this->process != 'ProcessPageAdd') return; $inputfield = $event->object; if($inputfield->name === 'template') { $regex = '#<\s*?select\b[^>]*>(.*?)</select\b[^>]*>#s';//regex to get all content (options) between the select tags $str = $event->return; preg_match($regex, $str, $match); $origoptions = $match[1];//get all original options $options = $origoptions; if(isset($_POST['template'])) wire('session')->selectedoption = wire('input')->post('template');//set session after POST if(wire('session')->selectedoption){ wire('session')->remove('selectedoption');//remove session } else { $options = str_replace("selected='selected'", '', $origoptions); //remove selected attribute on first load } $newoptions = '<option value="">'.__("Please select").'</option>'.$options;//create all options including the empty option tag at the beginning $result = str_replace($origoptions, $newoptions, $str);//replace the original options with the new options $event->return = $result; } }); Short explanation: The regex is used to get all options between the select tags (needed a little bit later to add the additional option tag on the top) The session is used to check if the page is loaded for the first time. If yes (no session created) than the pre-selected option will be removed, so that the "Please select" option will be selected on the first page load. The session will be removed afterwards. So this step is only necessary to get the "Please select" as pre-selected value on the first page load. Afterwards the additional option tag with "Please select" will be added to the original option tag which was grabbed with the regex. The final step is to output the modified select. At the moment I didnt find any problems or errors with this code, but if someone has some improvements please let me know. Best regards
    3 points
  4. A quick update. Thanks to lots of help from @szabesz we have fixed the issue with the Config Data section in PW Info panel from being slow. The latest version also: 1) Fixes a ERR_BLOCKED_BY_XSS_AUDITOR browser error if there are <script> tags in your template file and you are using the Template Editor panel to test code changes. 2) Adds a new option for opening links from the PW Info panel in a new browser tab (off by default) - this was requested by @szabesz above. 3) Revamped the init() and ready() code so that much less code is processed when Tracy is completely or temporarily disabled. It also improves efficiency for various conditional checks. 4) Several other minor tweaks / fixes. Please let me know if you come across any problems with this new version.
    3 points
  5. I didn't know they were called that - awesome! Only 6 weeks to go ... BTW - actually not that big of a Star Wars nerd
    3 points
  6. I hope you have been able to get this working. I will detail how I'm use Google Tag Manager for an upcoming project, just in case you still are having problems. Background I'm working on a new website where we are using an Ecommerce Widget. We normally use Piwik for basic analytics, however this Online Store solution uses Google Analytics to track things (shopping cart, etc). This is where Google Tag Manager becomes a great solution. We ended up using both Piwik and Google Analytics. In Google Tag Manager you create the needed Tags with Firing Triggers. In this situation, we created one for Google Analytics (using Universal Analytics tag) and one for Piwik (using a Custom HTML Tag). The Custom Tag is simple, you enter the Piwik code and save. Now that these tags are created, you take the Google Tag Manager code and add it to your website. Just follow the instructions, as listed. My website configuration has a _head.inc and _main.inc. You can see (above in the 2 files) where the Google Tag Manager code is put. It turns out to be a very clean solution when you need to track many things or have more than one analytical tool that needs to track things. One of the good things about using Google Tag Manager is that you can verify that the 2 Tags are firing, as you need them to. Additionally, you can create more Tags to track a multitude of things on your website. Google provides free training courses on Google Tag Manager, if you are interested: https://analytics.google.com/analytics/academy/ I hope this helps someone out.
    3 points
  7. In my case I have a parent template for events. Under this parent the editor can create events and he can choose between 4 different type of events (at the moment). Each of them has its own template and form with different fields. Therefore it is necessary in this case that editors can choose between these types (depending on which type of event should be added). Fe if the editor wants to add a new event with price, max. participants, deadline for reservation and so on.. he needs other input fields than if he wants to add only a date for a company vacation. It would be great if this could be part of the core (fe with the option to select in the settings if a "Please select" should be displayed or not).
    2 points
  8. FYI, one site I rewrote recently the honeypot fails entirely. I wouldn't like to add a captcha so added sblam, whuch works fine so far: https://sblam.com/en.html
    2 points
  9. I forgot to add this one. Verride Santa Catarina is among the most upscale hotels in Lisbon, set in a historic townhouse in the heart of the city. http://verridesc.pt/ It's a modular design that allows pages to be built using a set of blocks the admin can customise.
    1 point
  10. This week's version, ProcessWire 3.0.82, focuses on fixing several things reported from GitHub issue reports (dev branch commit log). So there are quite a lot of commits in this week's version, but none interesting enough to warrant a screenshot or real blog post. There was also one addition, which was support for repeater fields in the Setup > Fields > Export/Import functions. This week also brings several updates to the AdminThemeUikit module, which we may be pulling into the core dev branch as soon as next week. So if you are using AdminThemeUikit, be sure to grab the latest version, in addition to ProcessWire 3.0.82. That's all for this week. Have a great weekend!
    1 point
  11. Oh yeah, I agree it can be very useful. I have just managed to avoid the need so far, but your enhancement would make it much more functional and less prone to being ignored thereby creating problems. Maybe add a request in the appropriate Github requests repo?
    1 point
  12. @Juergen - nice work. I actually wonder if perhaps this should be the default behavior for this. I almost never allow editors to choose a template for child pages, but with this approach I might be more willing to do so in the future. Should this be a request to Ryan?
    1 point
  13. Hi @devonic and welcome to the forum. Could you post the errors? Did you set access restrictions on just the templates or on the fields themselves?
    1 point
  14. I'm always using field names like password, email, name or the like. I guess most bots are more likely to fill fields with those names than any cryptic names.. would be interesting to try that in your case and see if that helps
    1 point
  15. Is there a particular reason for this? Couldn't you just show a message such as 'no posts found in this category'? If the parent of this categories is the current page, why not just use $page->children rather than parent=$page->id? I see no way of doing this using one selector. $pages->count() is quite efficient actually. I'm no expert but I don't think 5 - 30 will hurt. In some cases (not necessarily the present case) this is the way to go. Have a look at $database.
    1 point
  16. The task is to change a runtime property (visibility) of a field and setting/saving a page field value if certain conditions are met. Hooks are great but not needed to solve this task.
    1 point
  17. Is the missing $ in your post a typo here in the forum? You need: $content .= $loginForm; Also, it depends on how your _main.php is set up. Is $content the final variable that is echo'd at the end, or is it $out or something else? Of course you need to use the variable that is actually used in your _main.php file. $content is just an example.
    1 point
  18. Personally, I wouldn't bother with the function. /includes/header.php <?php $metaImage = $page->closest("postThumbnail.count>0")->postThumbnail; if(!$metaImage) $metaImage = $pages(1319)->postThumbnail; ?> <meta name="twitter:image" content="<?= $metaImage->size(1200, 1200, ['upscaling' => true, 'cropping' => 'center', 'quality' => 90])->httpUrl ?>">
    1 point
  19. There's invisible recaptcha that only shows up in case of suspected bot activity https://developers.google.com/recaptcha/docs/invisible
    1 point
  20. Hello @modifiedcontent Composer safes you a lot of time on updating and installing PHP-libraries which you want to use in your project. I use more than 1 external PHP library on my projects, so it makes really sense in my case. Honeypot class is only one of them. If you have time you could read how to install it on your system. It seems to be difficult at the beginning, but there are also tutorial videos on Youtube that are really good and easy to follow. The only thing to mention: you have to work with the CLI (command line interface). If you want to install for example the Honeypot class you only have to write composer require dominiquevienne/honeypot into your CLI and if you want to update it later you only have to write composer update Thats all and the latest version will be installed. No need to look for updates manually. No need to install updates manually. So its a really useful solution to install libraries and keep them up to date with less work.
    1 point
  21. That would be up to 3rd party services (almost all services support some type of tracking) or developer (by creating trackable links, 1x1px tracking gifs etc)
    1 point
  22. @ROLAND_JUNO mine is like this. Using the new gtag. Just paste it in as the first item in the <head> section for your site like so: <?php namespace ProcessWire; ?> <!DOCTYPE html> <html lang='en'> <head> <!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-NUMBER"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-NUMBER'); </script> <!-- then the rest of your meta tage/page title/whatever --> <meta http-equiv='content-type' content='text/html; charset=utf-8' /> <meta name='viewport' content='width=device-width, initial-scale=1' /> </head> You find your specific code (and UA-NUMBER) on the google analytics website.
    1 point
  23. Double bother I need to think, think, think harder next time This is the first time I see these errors, probably I got intimidated... Yes please! The problem with this that I get the result in a not too tall box with lots of scrolling an clicking and the presentation of it is not as "good" as the one with the panel. What if there was a way to put custom settings onto the Panel Selector? Meaning module settings could be enabled/disabled for the Panel Selector, those one happens to switch on/of often. Currently I have no idea how the UI could be implemented for this, so this is just a blurry thought at this time.
    1 point
  24. I had the time to do some testing, here it comes (my MAMP Pro): API variables: 0.3ms Core Classes: 0.4ms Config Data: 270ms Version List: 14ms API variables + Core Classes + Admin Link + Doc Links: 0.9ms The result of d($config) is: Frontend: syntax error, unexpected end of file File: .../site/assets/cache/TracyDebugger/consoleCode.php:2 1: <?php if(!defined("PROCESSWIRE")) die("no direct access"); $page = $pages->get(1); 2: d($config) Admin: Same as above + 500: Internal Server Error: See the browser dev console for the actual error Why? It used to work. BTW, links in this Info panel do not not use _blank, why? I keep forgetting it which is kinda annoying after while. Is it just me?
    1 point
  25. Justin case someone looks for an answer, it is possible to dynamically set the selectable pages (instructions are in current PW page field options). And to dynamically change the parent of the "to be created pages" from the Create New textarea, it is possible to hook into InputfieldPage's method processInputAddPages, set "template_id" and "parent_id" configuration data on the fly with the information we have available such as the $page where the field instance is being called. If you take notice, later on the hooked method, this two options are read back to accomplish the page creation. $wire->addHookBefore('InputfieldPage::processInputAddPages', function($event) { $field = $event->object; $page = $field->hasPage; //Set the parent and template options, this are checked later to complete the task of adding pages $option_template = wire("templates")->get("template_name")->id; $parent_id = wire('pages')->get("name=options")->id; if($page->template == "some_template"){ //Example, change the parent depending on what template the field's currently in. $parent_id = $page->child('template=custom_options')->id; } $field->set("template_id", $option_template); $field->set("parent_id", $parent_id); });
    1 point
  26. @ROLAND_JUNO ... Add the code between <! - Google Analytics -> {GOOGLE ANALYTICS CODE} <! - End Google Analytics -> As below and in place UA-XXXXX-Y enter code ( tracking ID ) ... This is an example in _main.php from processwire 3.x ... More info: <?php namespace ProcessWire; // _main.php template file, called after a page’s template file $home = pages()->get('/'); // homepage $siteTitle = 'Regular'; $siteTagline = $home->summary; ?><!DOCTYPE html> <html lang="en"> <head id='html-head'> <!-- Google Analytics --> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-XXXXX-Y', 'auto'); ga('send', 'pageview'); </script> <!-- End Google Analytics --> <!-- THERE ARE EXAMPLES OF PROCESSWIRE 3.X DO NOT COPY THEM --> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title id='html-title'><?=page()->title?></title> <meta name="description" content="<?=page()->summary?>"> <link rel="stylesheet" href="<?=urls()->templates?>styles/main.css"> </head>
    1 point
  27. Ok, so if I understand it right, you want to force user to pick a template. I'm not sure if this fits your needs but with a bit of JS and hooks you can remove default value and set the template select required (with `required` html attribute), such that you cant get to the next step without deliberately picking a template wire()->addHookAfter('ProcessPageAdd::buildForm', function (HookEvent $e) { /** @var InputfieldForm $form */ $form = $e->return; $form->add([ 'type' => 'markup', 'value' => '<script>document.querySelector("[name=template]").selectedIndex = -1;</script>' ]); $template = $form->getChildByName('template'); if ($template) $template->attr('required', 1); });
    1 point
  28. I'm on Windows, so there aren't any. If there were, the zip file would not have been written to the directory anyway. The issue seems to be with deleting the temp file, which causes the rename function to return false, which is when the IOException is thrown.
    1 point
  29. You're welcome. I'm glad your problem got solved. You're right, thanks for pointing that. I was reading the source for urlSegments just today. Gotta love @ryan's humor // ProcessPageView.module /** * Get the requested page and populate it with identified urlSegments or page numbers * * @return Page|null * */ protected function getPage() { $config = $this->wire('config'); $shit = isset($_GET['it']) ? trim($_GET['it']) : "/"; // dirty $it = preg_replace('{[^-_./a-zA-Z0-9]}', '', $shit); // clean unset($_GET['it']); if($shit !== $it && $config->pageNameCharset == 'UTF8') { $it = $this->wire('sanitizer')->pagePathNameUTF8($shit); } // ... while((!$page || !$page->id) && $cnt < $maxSegments) { $it = rtrim($it, '/'); $pos = strrpos($it, '/')+1; $urlSegment = substr($it, $pos); $urlSegments[$cnt] = $urlSegment; $it = substr($it, 0, $pos); // $it no longer includes the urlSegment $selector = "path=" . $this->wire('sanitizer')->selectorValue($it, 2048) . ", status<" . Page::statusMax; $page = $this->pages->get($selector); $cnt++; } // ... }
    1 point
  30. Simplest way I can think of is to use PHP substr and strip_tags. The latter is very greedy so you need to tell it what to avoid [allowable tags]...(it get could messy very quickly). Anyhow, this is how we do it in the Blog module using those two PHP functions.
    1 point
×
×
  • Create New...