Search the Community
Showing results for 'runtime'.
-
You can hardly use this method, without caching the number of movies by director somewhere in the database. There's no internal counter for pagefield usage, so the only option besides runtime calculation is using a field, that'll hold the number of posts and updates on changes. You should probably use an hook on Pages::saveReady, which does update a "number_of_posts" field in the directors template when you save any post or when you save any director. For initial population of those fields you would need to heavily use uncache to prevent memory overflow, but, together with a not to short execution time, you can once loop over all directors to get initial counts set.
-
Polymer/html-imports blocked by .htaccess?
LostKobrakai replied to Osorio's topic in General Support
Nothing should break the pw bootstrap process, this topic is about the security issues of skipping it. The .htaccess line which prevents the polymer loading is blocking access to .php/.tpl/.inc and .html (see first post). The first three file extentions do have the potential to be dependent on processwire runtime variables, therefore accessing them should be handled by processwire. The last extention is in that rule, because before polymer nobody needed to access .html files directly from the client. They were only used by the .php files internally. So it was in the best interest to block access to them, too, so users cannot access those html chunks. Now with polymer that's not the case anymore, so just remove the .html from the rule to use them with polymer. Allowing more subfolders is also possible by editing the .htaccess rules and as long as there are only static files (js/css/html/img/…) it should not matter from a security standpoint. -
No problem. Here's the module I put together: <?php class SiteFilter extends WireData implements Module { /** * getModuleInfo is a module required by all modules to tell ProcessWire about them * * @return array * */ public static function getModuleInfo() { return array( // The module'ss title, typically a little more descriptive than the class name 'title' => 'Site Filter', // version number 'version' => 1, // summary is brief description of what this module is 'summary' => 'Add the current filter value as urlSegment1 for all internal links.', // singular=true: indicates that only one instance of the module is allowed. // This is usually what you want for modules that attach hooks. 'singular' => true, // autoload=true: indicates the module should be started with ProcessWire. // This is necessary for any modules that attach runtime hooks, otherwise those // hooks won't get attached unless some other code calls the module on it's own. // Note that autoload modules are almost always also 'singular' (seen above). 'autoload' => true ); } /** * Initialization function. This is where we'll attach our hooks. * */ public function init() { // minify page markup automatically wire()->addHookAfter("Page::render", $this, "addSegment1"); } public function isExternal($url) { $components = parse_url($url); if ( empty($components['host']) ) return false; // we will treat url like '/relative.php' as relative if ( strcasecmp($components['host'], wire('config')) === 0 ) return false; // url host looks exactly like the local host return strrpos(strtolower($components['host']), '.' . wire('config')->httpHost) !== strlen($components['host']) - strlen('.' . wire('config')); // check if the url host is a subdomain } /** * addSegment1 * * We have a session variable we'd like to append to all internal urls to persist site filters when * bookmarking, and sharing urls. This also allows filtered pages to be cached. Each template needs * to have segments enabled, and we use a regex value for allowed segments to prevent a runaway * cache. * @param HookEvent $event */ public function addSegment1(HookEvent $event) { // let's not mess with the back-end urls $cur_page = $event->object; if($cur_page->template == "admin") return; // Let's not pollute the page with domDocument warnings libxml_use_internal_errors(true); // event return value contains rendered markup $markup = $event->return; $currentFilter = wire('session')->settings_filter; if ($currentFilter == "") return; // we don't want to attempt minifying markup unless it's actually HTML if (strpos($markup, "<html") === false) return; $dom = new domDocument; $dom->loadHTML($markup); $dom->preserveWhiteSpace = false; $links = $dom->getElementsByTagName('a'); foreach($links as $link){ $url = $link->getAttribute('href'); $external = $this->isExternal($url); if($external === false){ if(strpos($url, $currentFilter) === false){ $url .= $currentFilter . "/"; $link->setAttribute("href", $url); } } } $newMarkup = $dom->saveHTML(); $event->return = $newMarkup; } }
-
Hello, I made a copy of the Textformatter Autoschema module to add additional Markups. I have included a additional regex to fetch all images which are inside a link. They should be modified with a little bit of additional markup to make CSS3 effects possible. Here is the copy of the module code with the changes. <?php /** * @author FlipZoom Media Inc. - David Karich * @contact David Karich <david.karich@flipzoom.de> * @website www.flipzoom.de * @create 201401-10 * @style Tab size: 4 / Soft tabs: YES * ---------------------------------------------------------------------------------- * @licence * Copyright (c) 2013 FlipZoom Media Inc. - David Karich * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is furnished * to do so, subject to the following conditions: The above copyright notice and * this permission notice shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ---------------------------------------------------------------------------------- */ class TextformatterBootstrapMarkups extends Textformatter { /** * ------------------------------------------------------------------------ * getModuleInfo is a module required by all modules to tell * ProcessWire about them * ------------------------------------------------------------------------ * @return array */ public static function getModuleInfo() { return array( // ------------------------------------------------------------------------ // The module'ss title, typically a little more descriptive than the // class name // ------------------------------------------------------------------------ 'title' => 'Bootstrap Markup changer with Schema.org', // ------------------------------------------------------------------------ // Version: major, minor, revision, i.e. 100 = 1.1.0 // ------------------------------------------------------------------------ 'version' => 100, // ------------------------------------------------------------------------ // Summary is brief description of what this module is // ------------------------------------------------------------------------ 'summary' => 'Converts standard tags into Bootstrap markup classes enriched with schema.org data.', // ------------------------------------------------------------------------ // singular=true: indicates that only one instance of the module is allowed. // This is usually what you want for modules that attach hooks. // ------------------------------------------------------------------------ 'singular' => true, // ------------------------------------------------------------------------ // autoload=true: indicates the module should be started with ProcessWire. // This is necessary for any modules that attach runtime hooks, otherwise those // hooks won't get attached unless some other code calls the module on it's own. // Note that autoload modules are almost always also 'singular' (seen above). // ------------------------------------------------------------------------ 'autoload' => false, ); } /** * ------------------------------------------------------------------------ * Searches for tags and adds the right attribute. * ------------------------------------------------------------------------ * @param string $string * @return string $string */ public function format(&$string) { // ------------------------------------------------------------------------ // H1 headlines // ------------------------------------------------------------------------ $string = preg_replace('/<h1(.*)>/Uis', '<h1$1 itemprop="headline">', $string); // ------------------------------------------------------------------------ // H2, H3, H4, H5, H6 headlines // ------------------------------------------------------------------------ $string = preg_replace('/<h([2|3|4|5|6]{1})(.*)>/Uis', '<h$1$2 itemprop="alternativeHeadline">', $string); // ------------------------------------------------------------------------ // Tables // ------------------------------------------------------------------------ //$string = preg_replace('/<table(.*)>/Uis', '<table class="table" $1 itemscope itemtype="http://schema.org/Table">', $string); $string = str_replace('<table', '<div class="table-responsive"><table itemscope itemtype="http://schema.org/Table"', $string); $string = str_replace('</table>', '</table></div>', $string); // ------------------------------------------------------------------------ // Unordered lists // ------------------------------------------------------------------------ //$string = preg_replace('/<ul(.*)>/Uis', '<ul itemscope itemtype="http://schema.org/ItemList">', $string); // ------------------------------------------------------------------------ // Ordered lists // ------------------------------------------------------------------------ //$string = preg_replace('/<ol(.*)>/Uis', '<ol class="itemscope itemtype="http://schema.org/ItemList">', $string); // ------------------------------------------------------------------------ // Paragraphs // ------------------------------------------------------------------------ $string = preg_replace('/<p(.*)>/Uis', '<p$1 itemprop="text">', $string); // ------------------------------------------------------------------------ // Links // ------------------------------------------------------------------------ //$string = preg_replace('/<a(.*)>/Uis', '<a$1 itemprop="url">', $string); // ------------------------------------------------------------------------ // Address // ------------------------------------------------------------------------ //$string = preg_replace('/<address(.*)>/Uis', '<address itemscope itemtype="http://schema.org/PostalAddress">', $string); // ------------------------------------------------------------------------ // Images // ------------------------------------------------------------------------ // THIS IS WHERE THE PROBLEM IS LOCATED //add additional markup to linked images $regeximg = '/<a(.*?)><img(.*?)(\/)?><\/a>/Ui';//grab all images inside links $imgsubstitute = '<a$1 itemprop="image" data-lightbox="gallery" class="img-responsive thumbnail"><div class="scalecontainer"><span class="roll"></span><img$2/></div></a>'; $string = preg_replace($regeximg, $imgsubstitute, $string); } } ?> Take a look at the code for images near the bottom. This is what I have added. Unfortunately this only works if the images are in a figure tag like this: <figure class="align_left"><a title="" data-original-title="" href="/site/assets/files/1807/bora_bora_3.jpg"><img alt="Rochen" src="/site/assets/files/1807/bora_bora_3.132x0-is.jpg" width="132"></a> <figcaption>Rochen</figcaption></figure> But it doesnt work if the figure tag is not there like: <a title="" data-original-title="" href="/site/assets/files/1807/bora_bora_3.jpg"><img alt="Rochen" class="align_left" src="/site/assets/files/1807/bora_bora_3.150x0-is.jpg" width="150"></a> I have tested the regex with a Regex-Tester and it works. Take a look here. But this is the result on my webpage: As you can see the first image has errors in the markup - this is the image which is not in a figure tag. The markup of the first image after the manipulation looks like this: <p> <a title="" data-original-title="" href="/site/assets/files/1807/bora_bora_3.jpg" itemprop="image" data-lightbox="gallery" class="img-responsive thumbnail"></a> </p> <div class="scalecontainer"> <a title="" data-original-title="" href="/site/assets/files/1807/bora_bora_3.jpg" itemprop="image" data-lightbox="gallery" class="img-responsive thumbnail"> <span class="roll"></span> <img alt="Rochen" class="align_left" src="/site/assets/files/1807/bora_bora_3.150x0-is.jpg" width="150"> </a> </div> instead of this <a title="" data-original-title="" href="/site/assets/files/1807/bora_bora_3.jpg" class="thumbnail"><div class="scalecontainer"><span class="roll"></span><img title="" data-original-title="" href="/site/assets/files/1807/bora_bora_3.jpg"></div></a> So it makes always a strange markup and I dont know why because everthing seems ok to me. Maybe someone has an idea
-
Hello @ all, I want to manipulate the markup of images added via the editor. In this case I have 2 possibilities: 1) To create a textformatter module or 2) to manipulate the output via jQuery General question: Will be the markup from a textformatter module cached or will it be created on runtime like jQuery? I prefer cacheable content so if it will be cachable I would tend to create a module instead of jQuery manipulation. Thanks in advance for your help.
-
It works like this: Add image to ckeditor (markup pasted in from plugin) Potential jQuery stuff happens on the ckeditor Markup is saved to database as it's in the editor Markup is loaded for frontend access from the database Potential textformatters are applied at runtime by php (cacheable by markupcache) Markup is send to the user Potential jQuery stuff happens (frontend) In 1, 2, 5 and 7 are the common places where you could bring in your custom logic. Which one you take depends on the use case.
-
I have a rather unusual need. I need to have two fields in my template that show the parent and grandparent of the actual page in a plain (readonly) text field. Let me explain. My tree is as such: - State - City - Point of Interest At runtime, it's easy to retrieve the city and state of the point of interest with $page->parent and $page->parent->parent respectively. But what I'd like to have two fields that show the actual output of those queries directly in the editor. For example: City: Hoboken, State: New Jersey. The main reason is that I'm trying to output these two fields in JSON (using Christian's WebServiceTemplate) so that an app developer can grab these results without making two extra calls to the database. A hook would probably do it, but I don't know how to achieve it. Any help would be greatly appreciated.
-
No Pete, flash is just one of options (eg. if browser doesn't support html5). Here on this link you can test various runtime options (link). From Github (link): "Plupload is JavaScript API for building file uploaders. It supports multiple file selection, file filtering, chunked upload, client side image downsizing and when necessary can fallback to alternative runtimes, like Flash and Silverlight." EDIT: Now I am reading my posts and it's looks like I am an Plupload advocate - NO I am not. This is interesting topic and only what I want is to recommend it because I have positive experiences with it. It was ~30 min. job for integration in my project, and all that works without any problems. Also it is widely used by Drupal, Wordpress, Django... developers, old project, open source... And about Flash/Silverlight - on developer side is to allow or not support for that (script configuration) . That's it. I promise that I will no more talk about Pxxxx Thanks to HTML5, we can exclude Flash/Silverlight/Java technologies and use only javacsript + HTML5 to get all that magic on client side (canvas object for image resize, "multiple" for simple multiple file selection). regrads
-
Your selector is wrong "name=$name" would be parsed to "name=directly-off-root.html", but your page's name is still only "directly-off-root" without the html. As you're not using not html'ed names I would suggest just adding it to the name of the pages directly. Your hook to Page::path just changes to url on runtime, but does not modify the "name" field your selector checks for. To keep your code clean it's also best to not couple two different things, appending ".html" and masking out a parent page, into a single hook. Then you'll see that Page::path isn't the right place to handle your first issue.
-
I find it interesting that it is specifically making the table name lower case on my side. I'm going to need to look at this properly as well. I think I'll land up just doing a test at runtime to see which one it is...
-
I used the raw table name (processredirects) as that what was in my database when I wrote the module. In fact, I've just installed a fresh copy of it, and the table is called "processredirects". Perhaps this could be different versions of MySQL changing the case at runtime?
-
The problem was a database timeout. I fixed the timout problem by using the following to reconnect if needed. $data = $backup->run($web); //force reconnect if database has been lost due to long job runtime try { $this->setJobData($id, $data); } catch (Exception $e) { $this->modules->wire('database')->closeConnection(); $this->setJobData($id, $data); } Not the most beautiful solution. I would prefer to have a $db->ping() method as there was with mysqli. Maybe that would be a good extension to the DBO? I created a pull request: https://github.com/ryancramerdesign/ProcessWire/pull/1097 Its not dead important but I think it would be nice.
-
Hi markoj, First welcome to PW and the forums! Yes, that's possible. MB allows you to 'allow HTML in menu items title'. See that option when editing your menu under the tab 'main'. You would need to be a superuser or have the permission 'menu-builder-allow-markup' in order to set and use that option. Secondly, your 'Ditto' in this case would be Hanna Code: https://processwire.com/talk/topic/3745-hanna-code http://mods.pw/4b Install the module. Otherwise, if you included your whole HTML in your menu item's title in MB, it won't look pretty and the HTML will be rendered. The <h1> would be especially ugly there .. I don't know where your images will be coming from but in this example, I assume they are saved in some page with an image field called 'img' OK, once you've installed HC module (taking care to follow all the instructions, create a Hanna Code of type PHP. Let's call it 'test'. Add the following code to it. This is just example code; $p = wire('pages')->get(1317); #$out = $p->img->first()->size(0,50)->url; $out = $p->img->eq(0)->size(0,50)->url; $out = "<img src='$out'>"; echo $out; Here we assume your images are stored in a field called 'img' and that field allows multiple images. We assume that field is populated in a page with ID 1317. We are also grabbing the first image and resizing it. Save the HC. Head over to MB (assuming you've installed the module). Create a menu and enable 'allow HTML...' as I described above. Add at least one menu item to your menu. Enter something the below in your menu item's title. We assume the title is called 'Blog'. [[test]]<span>Blog</span> Here we use span for convenience, otherwise <h1> will be rendered in the menu title drag and drop handle (hacky I know). We'll replace the <span> with <h1) at runtime. In your template file you could render your menu as follows: //get MB $menu = $modules->get('MarkupMenuBuilder'); $out = $menu->render('My Menu Title', $options);//holds rendered menu //get hanna code $hanna = $modules->get('TextformatterHannaCode'); //render the [[test]] HC + replace <span> with <h1> echo $hanna->render(str_replace('span', 'h1', $menu->render($m, $options))); See MB's documentation about what you can pass to $options (e.g. you may not wish to use <ul> and <li> in your menu. This is just a quick example. Maybe things could be done better.. ....And you probably want to edit this menu yourself...clients will probably be confused with [[test]]Blog
-
Hi, I think I'll put back this code in a .php file. But the HannaCode module has enabled me to be aware of some errors. And apparently, I can't use a dash or a whitespace with $form. I've modified the code to be: <?php /** * Example of a simple contact form in ProcessWire * */ // set this to the email address you want to send to (or pull from a PW field) $emailTo = 'whatever@gmail.com'; // or if not set, we'll just email the default superuser if(empty($emailTo)) $emailTo = $users->get($config->superUserPageID)->email; // set and sanitize our form field values $form = array( 'Nom' => $sanitizer->text($input->post->fullname), 'Courriel' => $sanitizer->email($input->post->email), 'Message' => $sanitizer->textarea($input->post->comments), ); // initialize runtime vars $sent = false; $error = ''; // check if the form was submitted if($input->post->submit) { // determine if any fields were ommitted or didn't validate foreach($form as $key => $value) { if(empty($value)) $error = "<h4 class='error'>Veuillez vérifier que vous avez complété tous les champs.</h4>"; } // if no errors, email the form results if(!$error) { $subject = "Formulaire de contact"; $message = ''; foreach($form as $key => $value) $message .= "$key : $value\n"; mail($emailTo, $subject, $message, "From: {$form[Courriel]}"); $sent = true; } } if($sent) { echo "<h3>Merci, votre message a été envoyé.</h3>"; // or pull from a PW field } else { // encode values for placement in markup foreach($form as $key => $value) { $form[$key] = htmlentities($value, ENT_QUOTES, "UTF-8"); } // output the form echo <<<_OUT $error <form action="./" method="post"> <p> <label for="fullname">Vos Prénom et Nom</label><br /> <input type="text" id="fullname" name="fullname" size="46" value="$form[Nom]" /> </p> <p> <label for="email">Votre e-mail</label><br /> <input type="email" name="email" id="email" size="46" value="$form[Courriel]" /> </p> <p> <label for="comments">Message</label><br /> <textarea id="comments" name="comments" rows="5" cols="60">$form[Message]</textarea> </p> <p><input type="submit" name="submit" value="Envoyer" /></p> </form> _OUT; } But I still receive the message twice when completing the form in Firefox, and Chrome. But only once from Opera (a recent version also). EDIT: Opera twice also... Does someone have an idea? I'm doing some research... Also, does this form seem secure? Thanks in advance NB: @Jan Romero -> Thank you for the curly braces...
-
I will turn on debug mode and see if I can get any errors. (nothing is showing up in the log though). @Nico knolI: Thanks, I think the issue is I have one module that is doing 4-5 related things to drafting pages and publishing them, but those things should probably be split into separate modules. (I think) A process module that is not auto load (which I just learned from your post), and then several autoload modules need access to the runtime hooks (altering page listings, adding draft buttons, edit draft buttons, etc.)
-
I think your 'another thought' is a better approach since it allows for more granularity, i.e. it targets individual menu items rather than the first approach which targets the whole menu in terms of including natural child pages. I don't think there is a need for the second option 'yes/no' though unless am not getting it? By using the 'include natural children' option, you imply that you want them to be displayed. The way I think I'll do it: 'include_children' => 0//default = no 'include_children' => 1//yes, but only in menu, i.e. render() 'include_children' => 2//yes, but only in breadcrumbs, i.e. renderBreadcrumbs() 'include_children' => 3//yes, in both //number of child nesting levels to show IF include_children > 0 //include_children_levels => 1//default, i.e. show only immediate children [or child in case of breadcrumbs] //include_children_levels => 2//etc....show up to grandchildren/grandchild, etc.. The include_children can be tricky though....One might end-up with lots of sub-menus! But this is is optional, so up to the developer really. Apart from some coding issues I may not have thought of yet, the visual MB aspect has to be considered. Those natural child pages will not be included in the saved menu items, hence will not be displayed in the menu tree in the back-end (ProcessMenuBuilder). They will only be included in the front-end output during runtime. That may confuse your editors, but nothing you can't educate them about, and this is optional anyway. Edit: Or...in the spirit of flexibility and granularity....in MB admin, also add an include_children_levels text (int) box next to an include_children checkbox. Then in the front-end, render() and renderBreadcrumbs() will be guided by: if the setting include_children_levels is empty AND you have an $options = array ('include_children' => xx, 'include_children_levels' => zz), the level set in $options takes precedence and is applied overall except for menu items where the setting include_children_levels is NOT empty; an explicit level set at menu item level will override any $options setting. Would such a workflow work for you?
-
How can I get the user profile language?
enricob replied to enricob's topic in Multi-Language Support
Thanks Soma, that's what I though... But if you check the value of the language field of the current user object while he's viewing the site (not by querying the $user object, but for example looking at the database) you'll see that the value never change when the user change the navigation language, while $user->language value does. So, if $user->language give me the current navigation language (that changes at runtime) how do I get the language value of the current user though the api? -
Where is it done, the change on runtime?
-
User language is tied to what language is requested. So it changes on runtime. User language set in admin is for backend primary. If you need user to set a language for frontend you could add a field to user and check that.
-
Hello fellow wirecionados, looking at the roadmap to 3.0 always gives me the good feeling of being on the sunny, futureproof side when using Processwire. Everything we already have together with the features planned is all I ever needed from a CMS. At least this is what I thought until that next idea came to my mind. Actually, there's one thing about Processwire that I have been struggling with from the start and until now: the hook system. I know, the hook system is deeply enrooted in Processwire (as can be seen from the fact that it's implemented in the Wire class that virtually every other class extends) and therefore is one of the key aspects for its success in the first place. It allows for the relatively loose coupling of components, with a lot of the core functionalities being implemented as modules. This makes for the great extensibility that Processwire is famous for. There aren't many parts of Processwire that can't be tweaked and modified to anyones needs by developing a module that alters some core functionality. I'm really glad about that and probably wouldn't have started to use Processwire in the first place, if the hook system didn't exist. That all being said, I also see some more or less problematic downside to the current implementation. It's sometimes pretty hard to find out, where functions are actually implemented. How long did it take you to find out that the actual logic for Page::render() is implenented in PageRender::renderPage()? While this kind of flexibility is just great, the implementation is not very verbose. This makes things harder than they have to be – especially for beginners. Just to make the argument above worse, there are several different ways to define a hook: addHook(), addHookAfter() & addHookBefore(), and all can be called either with a Class name or on an object. This makes it even harder to find modules, that hook into a particular function. I know, we have Soma's fabulous Captain Hook, and I use it all the time, but it still feels more like a workaround than like a solution. Speaking of Captain Hook, there's still a „Crocodile Hooked“ missing, a central repository that keeps track of all methods that are hooked to another method, including (private) site modules – and if possibly available at run time. Hooks for classes are saved in a static variable of Wire, but local hooks can only be fetched from that particular instance of an object. The convention with the three underscores in front of a function name makes functions harder to find. It is a nightmare to debug. If you ever tried to follow a request through the system with Xdebug, maybe involving some hooks placed by modules, you probably know what I mean. You have to go through Wire::runHooks() and __call() again and again to get where you want. It also prevents some of the convenient features of your favourite IDE™ (e.g. code completion, parameter hints when using a function, go to the definition of a function by clicking on it, etc.) from working in some cases. While one could definitely argue, that this is the fault of the IDE used, it's still slowing down work and not likely to be changed anywhere soon. Please excuse me if this was too ranty and even more correct me if anything I mentioned is an error on my side. I have to emphasize that none of these downsides prevents anyone from getting something done, it just makes it a tad less obvious and comfortable. Thinking through the things that I don't like about the current implementation of the hooks system, it came to my mind, that what we currently have here is kind of a non-verbose version of a „traditional“ event system and maybe what's missing could be more verbosity, so maybe such an event system (that implements the mediator pattern) could be of help? What I have in my mind here is the Symfony EventDispatcher or the Drupal8 EventDispatcher component, which is similiar to the CakePHP Events System and the handling of Events in Laravel. Let's look at how a solution to the problems mentioned might work by way of example using the Symfony EventDispatcher. In this particular example, the difference would be that Page::render() would actually be implemented in the Page class but just dispatches an Event.render event. Functionally no real difference, but much more verbose and therefore it is much more clear, that you will find the implementation anywhere a listener for Event.render is added. A new implementation could use just one method to add listeners (e.g. EventDispatcher::addListener()). Execution before or after an event will have to be handled by multiple events where this makes sense. Because the event dispatcher is the application-wide sole instance where event listeners are stored, it's easy to get all registered event listeners at runtime (using EventDispatcher::getListeners()). No more underscore's, just calls to dispatch events and calls to listeners. Debugging get's as smooth as it get's with loose component coupling. No more running through __call() all the time, always be able to check the defined event listeners. Having separated before and after events prevents you from some running through runHooks(). The added verbosity also helps to grasp the existing architecture quickly. Most of the IDE comfort functionality that doesn't work now should work with the Event System in place, because functions are always really where they are expected and with the exact same name. As an added benefit this system is very well known to a lot of developers already. But there are also some downsides for sure: Added verbosity is, well, verbose. More keys will have to be hit to get something done. Method and property would have to be implemented differently. This can be done by sending events on missing methods/properties, but it certainly looses some of the appeal it has now. The key argument would for sure be, that it breaks compatibility with a lot of core and user contributed modules. This is definitely true, so there shouldn't be an easy decision on this one. I thought I'll use the time before 3.0 to bring this one up, because as I understand it, the next major will break some stuff either way. Also I think that it should be possible to do the switch by in the beginning only deprecating the old hook system while keeping it functional, by translating calls to the old functions to adding and calling event listeners. This will have a performance impact, but would make a gentle transition possible. Now I'm really interested on your opinions on this topic. Do you already like the current implementation and wouldn't want to loose it? Do you have other problems with hooks? What kind of solution could you imagine? Is such a deep change realistic (and worth it) at all? Thanks a lot for your feedback Marc
-
Well, in fact this was worded the wrong way around, for sure it's the IDE that should support things that make it easy to work with a piece of code and not the other way around. That said, when writing a piece of software the author can make it more or less easy to do static analysis of the code. The information that is gatherable by static analysis enables IDEs to do their "magic" in providing all kinds of convenience when working with code (look at PhpStorm's features to see what this might include). It makes it also more easy to work interactively with a debugger like Xdebug, or code quality tools like PHP Mess Detector, PHP Code Sniffer and others. All kinds of code that is only available at runtime is not available to static analysis and thereby prevents some features of these tools from working correctly. The most clear example is code executed through eval(), but also magic functions, objects loaded by passing the class as a string argument to a function or functions executed by hooks can make problems here. I think it makes a lot of sense to prioritize having a concise, human-friendly API over making the code well-consumable by static code analysis. Still it would be great to improve in this sector to benefit as much as possible from the existing tools in the PHP world.
-
Another thing to your entry post, please use the code boxes for code. foreach($myPages as $p) { $p->set("your_new_field", $p->field.$p->anotherfield); //Field is runtime only } Maybe this works. You'd need to fill the field for each page. Even if it's different contentwise.
-
It is possible to swap the template file on runtime so that a page can have multiple template files. Maybe this is sufficient for you. This is possible with the Module FieldtypeSelectFile. You have to check the checkbox "Change Page Template" in the module settings and select the file to render in a page.
-
There's currently no way to implement this. Each template does have a single fixed set of fields. That is at least the answer to the backend structure. What you can do is provide a own php class (subclass of Page) to the "parent" entity. This class could then populate itself at runtime with the fields of those childpages you mentioned. This way you could at least maintain the structure in your code. The option to set such a class is in the template settings if you enable advanced mode. Maybe this could even be done with hooking the Page class, and without using the advanced mode settings.
-
@Peter - how many hanna codes do you usually use on the average site? My usage has been maybe 4-5 hanna codes on a site, or maybe as many as 10 on a really complex/large site; I do think maybe tags could help here on this page in terms of organizing them, but also i don't expect my clients to be interacting with the hanna codes list so this would be more of an admin convenience. sounds trickier than the templates, b/c the hanna codes are used randomly within text areas, or text fields - and are processed at runtime to the output; not that it would be impossible, but it might be a process that needs to run to collect all of that data and could take a lot of processing depending on the # of pages in the site.. I do agree some module to get a "hanna code report" than could generate and be able to process something like 50-100 pages at a time before generating the entire report; this could be very useful, because we might want to see where a particular one is being used; personally I always try and come up with solutions that avoid hanna codes if at all possible and are equally easy and potentially more elegant, and as such i never have more than a handful of hanna codes per site; Perhaps some of your hanna codes could be replaced with other solutions? they are always sort of a risk being that they are inserted into RTE, so not as bulletproof as something like a validated text input.. I always provide complete documentation for all hanna codes including the code itself that can be copied and then usage instructions, using my docs and docs tab system, as well as often inline using the Markup Textareas, so from the end user perspective, they can use any available hanna code right on the page (or also input with the helper module); but i do think that having a description field would be handy, especially if you come back to a project after some time, you could see more easily what each one does, at a glance..
- 3 replies
-
- 1
-
-
- UI
- Management
-
(and 2 more)
Tagged with: