Leaderboard
Popular Content
Showing content with the highest reputation on 08/22/2014 in all areas
-
So you've developed this shiny new website but your editors and marketing guys keep complaining they need more "native embedded content" with shiny share and retweet buttons because otherwise their text will look like ...text? Look no further: This processwire module has you covered! TextformatterOEmbed for processwire What it does At this point this module basically wraps the fabolous Essence PHP library by Félix Girault and adds some processwire magic to parse your boring Textareas and make your content look more bling blingthan ever before. Disclaimer: This Module is heavily inspired by TextFormatterVideoEmbed by the awesome guy who created processwire: RyanCramer. Requirements php 5.4+ curl and/or allow_fopen on Features Supports the following 32 providers out of the box (That's a lot of Hanna-Codes you can get rid of now, eh?): Add your own providers in the blink of an eye (if you're not good at regex - like me - it will propably take you a cup of coffee and a google search) Easy styling: Wraps embedded items with customizable BEM-Style classes including modifiers for every provider and embedtype. Choose to either add CSS directly in the modules configuration or to your existing stylesheets Choose to add pre defined Fluid Video CSS for your responsive design (or - again - feel free to add your own) Usage Click check for new modules in ProcessWire Admin Modules screen. Click install for the module labeled: "oEmbed for processwire". Install the module Open the modules Settings page Add css classes either within the "Custom CSS" field or in a seperate CSS file. Every provider is wrapped with the following markup: <div class="pw-oembed pw-oembed--providername pw-oembed--embedtype"> <div class="pw-oembed__inner pw-oembed__inner--providername pw-oembed--embedtype"></div> </div> If you're not happy with the "block" class .pw-oembed you can rename it to something you like better using the modules config. Every embedded media item and it's respective inner wrapper has two modifier classes: One for the provider (i.e. youtube, twitter...) and one for the media type (one of photo, video, link or rich according to the OEmbed specification). This should be enough classes to add some fancy icons, adjust widths per provider or whatever else you like to do. If you're missing a provider don't hesitate to open a pull request (see roadmap first) and I'll do my best to add it as soon as possible. In the meantime you can extend the available providers found in lib/essence/providers.php in the modules settings using the following JSON-Format (remember that you'll have to properly escape the regex): [{ "23hq" : { "class" : "OEmbed", "filter" : "#23hq\\.com/.+/photo/.+#i", "endpoint" :"http://www.23hq.com/23/oembed?format=json&url=%s" } }] Roadmap Add moaaar providers:Facebook (currently not providing a "native" oEmbed API) Google Plus (currently not providing a "native" oEmbed API) support for more fancy integration of Instagram posts (currently there are "just" images without fancy sharing stuff that will be embedded) Render only one javascript (i.e. ) when there are multiple items of the same provider Propably make this module more generic and add services as submodules at some point World domination10 points
-
Hi blad - take a look on the Input tab of your images field and check the "Display thumbnails in page editor" option Of course it doesn't float them like you have, but you can use the grid mode toggle for that - button at the top right of the field in the page editor. PS Not meaning to suggest your enhancements aren't nice by the way6 points
-
Absolutely not - I like what you have done - you just might want to consider changing the layout via a hook instead of modifying the core.4 points
-
Something like this will work: <?php /** * On a page that loads the widgets * */ $widgets = $pages->find("parent=/widgets/"); foreach($widgets as $widget) { $widget->set('motherPage', $page); echo "<div class='widget {$widget->template->name}'>"; echo $widget->render(); echo "</div>"; } <?php /** * logic on a widget page * */ // The $page variable of the mother Page bound to $motherPage. $motherPage = $page->motherPage; // Throw 404 if a guest access the widget directly if(!$motherPage && !$user->isLoggedin()) throw new Wire404Exception(); echo $page->body;4 points
-
Edited: read this https://processwire.com/talk/topic/7379-module-altgrid/3 points
-
@xorotle: you can use the underscore for that or you can configure something other in your site/config.php for $config->ignoreTemplateFileRegex see: https://github.com/ryancramerdesign/ProcessWire/blob/dev/wire/config.php#L249 if you define something in your site/config.php it overrides the setting from wire/config.php.3 points
-
Sorry, but this question has nothing to do with ProcessWire. For Foundation support better go to Stack Overflow or some other Foundation support.3 points
-
Apologies for the brief reply, on mobile. https://processwire.com/talk/topic/3145-multiple-views-for-templates/page-2#entry328763 points
-
Just needed the same and $config->pageNumUrlPrefix is working perfectly fine for me. You can translate the prefix at /processwire/module/edit?name=LanguageSupportPageNames Hope it helps for you or anyone else stumbling across2 points
-
Blad, Nice effort. However, just wondering, how is this different from the grid view already available in ProcessWire image fields? Secondly, I am not sure this is a 'suitable' tutorial because you are editing/hacking a core file which is never good practice. It will get overwritten with upgrades. Edit: OK, so Adrian beat me. @Adrian scores are now tied at 1 - 12 points
-
Hi everybody, As much as we hate the CAPTCHA, it is still used. I decided to share my solution of using ProcessWire forms with CAPTCHA. My goals were quite simple: 1. Create a form and customize it. 2. Get an Inputfield for a page field and append this Inputfield to the form. 3. Display a CAPTCHA. 4. Process the form and check its fields for correctness. 5. Check the CAPTCHA. 6. If steps 4-5 fail, display the form back with the user input intact. What I found to be not quite easy was how to push a different CAPTCHA into an already submitted form. (A spoiler: this is done quite smoothly with the power of ProcessWire's Inputfields.) Let's start, then. My Form class has several methods: appendFields() accepts an array of field names, gets their Inputfields from a template and appends these to the form displayForm() adds a CAPTCHA and returns the form's HTML processForm() checks the CSRF session ID and user input and delegates CAPTCHA verification getCAPTCHA() returns the html for the CAPTCHA checkCAPTCHA() checks the user input against the CAPTCHA and sets the verification flag to true or false. That's mostly it. Now to the code itself. class Form { public $form; public $captchaVerificationResult; // captcha verification flag (bool) public function __construct () { // form is created upon class instantiation $form = wire('modules')->get("InputfieldForm"); $form->action = wire('page')->path; $form->method = 'post'; $form->attr("id+name", 'form'); $form->attr("class", 'pure form'); // I use PureCSS class name here as an example // how form items are displayed can be customized $form->setMarkup(array ( 'list' => "\n{out}\n", 'item' => "\n\t{out}\n\t", 'item_label' => "\n\t\t<label class='pure-form' for='{for}'>{out}</label>", 'item_content' => "\n\t{out}\n\t", 'item_error' => "\n<p><span class='ui-state-error'>{out}</span></p>", 'item_description' => "\n<p class='description'>{out}</p>", 'item_head' => "\n<h2>{out}</h2>", 'item_notes' => "\n<p class='notes'>{out}</p>", ) ); // form classes can also be customized $form->setClasses(array ( 'list' => 'Inputfields', 'list_clearfix' => 'ui-helper-clearfix', 'item' => '', 'item_required' => '', 'item_error' => 'ui-state-error InputfieldStateError', 'item_collapsed' => '', 'item_column_width' => '', 'item_column_width_first' => '', ) ); $this->form = $form; } public function appendFields ($fields) { /* * $fields is an array of field names * * for each field name a corresponding Inputfield is fetched from a page * and appended to the form * */ $page = wire('pages')->get("999999999"); // this is the page that has your fields foreach ($fields as $f_name) { $field = wire('fields')->get($f_name); $if = $field->getInputfield($page); // this page must have field name $f_name among its fields! $this->form->append($if); } /* * * CAPTCHA placeholder */ /* * create an InputfieldMarkup field, * give it an ID and append to the form * * Later this Inputfield can be easily found by its ID. * * */ $inputfield = new InputfieldMarkup; // inputfield markup is appendable to form! $inputfield->id = 'captcha1'; // id of the InputfieldMarkup with CAPTCHA $this->form->append($inputfield); /** * finally, the SUBMIT button * */ $submit = wire('modules')->get('InputfieldSubmit'); $submit->skipLabel = Inputfield::skipLabelBlank; // remove the label $submit->name = 'submit_save'; $submit->value = "Save"; $this->form->append($submit); } public function get () { return $this->form; } public function displayForm ($form) { /* * Each time the form is displayed, the CAPTCHA should be there * * So, behore doing $form->render() let's get an InputFieldMarkup field by ID * and pour some fresh CAPTCHA in it * * */ $form->children->findOne("id=captcha1")->value .= $this->getCAPTCHA(); return $form->render(); } public function processForm ($form) { try { $form->processInput(wire('input')->post); wire('session')->CSRF->validate(); } catch (WireCSRFException $e) { die ($this->displayForm($form)); } $this->checkCAPTCHA(); // sets class property $captcha_verification_result to false/true if (!$this->captcha_verification_result) { $form->children->findOne("id=captcha1")->value = "Wrong captcha, try again <br />"; // this will go before the CAPTCHA code die($this->displayForm($form)); } else { // let's do some simple checks // you can and should do more of yours, of course $email = $form->get("b_email"); if (filter_var($email->value, FILTER_VALIDATE_EMAIL)) { $email->error = "Incorrect email format"; } if ($form->getErrors()) { // the form contains errors, display it with user input die($this->displayForm($form)); } else { echo "Thanks for the submission!"; // everything is just right } } } public function getCAPTCHA () { /* * * $captcha_html = your CAPTCHA code * */ return $captcha_html; // have a lovely CAPTCHA } public function checkCAPTCHA () { /* * * get some response and check it * * */ if ($response->failed) { $this->captchaVerificationResult = false; } else { $this->captchaVerificationResult = true; } } } Here's how this can be used: $form = new Form(); $formFields = array ("name", "email"); $form->appendFields($formFields); $newForm = $form->get(); if ($input->post->submit_save) { // user submitted the form, process it and check for errors $form->processForm($newForm); // the form was processed successfully because nothing die()'d. Now it's time to play with what's been submitted. } else { echo $form->displayForm($newForm); // if it's not been submitted, just display it and the CAPTCHA } With this being just a generic idea on how to do form processing with CAPTCHA, I hope portions of this code will prove helpful in your development. Your comments, corrections and suggestions are very much welcome.2 points
-
I like the system how it is now. I just give tabs names like "_sidebar" to distinguish them from normal fields. @ivan: Just create a template called "default" or whatever including all the fields you want to use in all templates. Then - when you create a new one - just select "default" in the field which asks you if you want to copy some fields of another template.2 points
-
Markup Simple Navigation Module While there was a lot of people asking how to make navigation, and there were many examples around already (apeisa, ryan...) I took the chance to sit down 2-3 hours to make a simple navigation module. It has even some options you can control some aspects of the output. Installation: 1. Put this module's folder "MarkupSimpleNavigation" into your /site/modules folder. 2. Go to your module Install page and click "Check for new modules". It will appear under the section Markup. Click "install" button. Done. Technically you don't even need to install it, after the first load call ( $modules->get("MarkupSimpleNavigation") ) it will install automaticly on first request if it isn't already. But it feels better. However, it will not be "autoloaded" by Processwire unless you load it in one of your php templates. Documentation: https://github.com/somatonic/MarkupSimpleNavigation/blob/master/README.md Modules Repository processwire.com mods.pw/u Download on github https://github.com/somatonic/MarkupSimpleNavigation Advanced example with hooks creating a Bootstrap 2.3.2 Multilevel Navbar https://gist.github.com/somatonic/6258081 I use hooks to manipulate certain attributes and classes to li's and anchors. If you understand the concept you can do a lot with this Module.1 point
-
Hi I am thinking about offering a web development services in my country. I have many questions and I don't know where to ask but I think you guys could help me a lot. I want to offer simple websites that are easy to do in PW. Some simple websites for businesses, services, local businesses and so on. No e-shops, apps or too complicated stuff... When I look at websites that offer web development services, to me they clearly suck. I made some Google searches ... I can make a list of things that I could do better than them in my online presentation... some websites look like from 2002. Really horrible IMO... However, I still don't say it is going to be easy. I am good at HTML, CSS, SCSS, Foundation 5 - so designing a template is not a problem. I have not fully learned JS and jQuery, but have gone through them in CodeCadamy along with PHP, Ruby, Python ... so I have almost completed CodeCadamy. Foundation 5 offers many plugins that I am comfortable using, so I am not sure how much of JS/jQ do I need ... And also I still need to get comfortable with PW since I have not really even tried it. So here are my questions... 1. What coding knowledge should I make sure I have before starting? 2. I am a high school student do you think it is manageable to do about 2 simple projects a month? 3. What about webhosting? Should I get some kind of reseller hosting? Which is the best one? Mediatemple looks good to me. Many big brands use their hosting, so I figured it could be more high-end and reliable solution. 4. How would you recommend getting first clients? 5. Where can I learn more about communicating with clients, what question to ask, what to be careful about and so on? 6. What should I charge for simple website ? Some static pages, custom responsive design, contact form, Google maps, maybe a simple blog, CMS access 7. Any other tip that you think could be helpful? Thanks, Marek1 point
-
hey adrian, yep no need to tagged them as expired, just exclude them.1 point
-
Probably the easiest way would be using Schedule Pages. If you need the unpublish date to be automatically set to x days after publish, you'll need to write a simple module to auto-populate the value of field 'publish_until'.1 point
-
new german updates for actual PW dev 2.4.14 (22 August 2014). Zip contains only updated/added files (in comparison to the default 2.4 lang pack). updated files: wire--modules--inputfield--inputfieldckeditor--inputfieldckeditor-module.json wire--modules--inputfield--inputfieldimage--inputfieldimage-module.json wire--modules--process--processfield--processfield-module.json pw-lang-de-dev-update.zip1 point
-
Macrura has developed module for this scenario (I think): https://processwire.com/talk/topic/6417-processwire-profields-table/?p=64275 The other thing - if you just want to make use of creating child pages with the PageTable interface, rather than actually use them in a PageTable field, check out: https://processwire.com/talk/topic/6102-batch-child-editor/?p=59733 The latest version's edit mode works very similarly to the PageTable edit mode - take a look at the screenshot for "3. Edit" in the first post. You can add new, sort, delete, quickly rename, and click to edit all fields in a modal popup.1 point
-
Frankly, I have not thought and I just did. Create a hook module is the best way.1 point
-
Oh okay, so in the options are just defaults as fallback. And in templates I can use different. Thanks!1 point
-
Sorry you can delete this topic. For me it's useful because I want my client doesn´t have to click to see all pictures and write descriptions.1 point
-
This post should be helpful: https://processwire.com/talk/topic/4960-limit-number-of-pages-that-can-be-added/1 point
-
I'm not sure about that notices loop, if you didn't delete the install.php for example does that prevent your $session->redirect ?1 point
-
This seems to work. At least through some simple tests. public function redirectMe($event){ $page = $event->arguments(0); $errors = false; foreach(wire('notices') as $notice){ if($notice instanceof NoticeError) $errors = true; } if (!$errors) $this->session->redirect($this->config->url->admin . "/processwire/news/"); }1 point
-
Thanks Martijn, That got me thinking, maybe I can just check the notices? $errors = false; foreach(wire('notices') as $notice) { $notice instanceof NoticeError ? $errors = true : ""; } Haven't tried that yet, just riffing. Will report back.1 point
-
I do think field errors are cleaned in the InputfieldWrapper render() methode. So maybe you need an additional hook before InutfieldWrapper render and loop through the fields and count the errors.1 point
-
Moved the topic from "Community Support > General Support" to "Off Topic > Dev Talk".1 point
-
Btw.: Fieldsets as fields maybe don't make sense in the backend but it makes a lot of sense if you're writing a module or just using the API for a form.1 point
-
But PLZ don't post that code in here inline, it's crazy1 point
-
hi marek! unfortunately there will always be someone who gets paid more money for a worse job/website so 1) don't be afraid, just do it! the first step is always the hardest and you will NEVER know everything, especially not in our fast web-world 2) coding skills are only a part of your job as a freelancer and many other parts (client communications, selling/marketing strategy and so on) you can not learn via internet... i wish you the best and i think you are well prepared! that's a very good advice!1 point
-
So, I'm just trying to gain some experience by making a second installation on my local mac... If I'm correct, I would have to add the new data into these places: Folder name: mdbnl Desired address in my browser: mdbnl/ ~/Sites |`-- _vHosts | `-- domains | `-- mdbnl | |-- htdocs | `-- index.html | `-- logs Vhosts (_vHosts/mdbnl.conf): <VirtualHost *:80> DocumentRoot /Users/marinusdebeer/Sites/domains/mdbnl/htdocs/ ServerName mdbnl ErrorLog /Users/marinusdebeer/Sites/domains/mdbnl/logs/error.log.txt CustomLog /Users/marinusdebeer/Sites/domains/mdbnl/logs/access.log.txt common </VirtualHost> In the hosts file I should add: 127.0.0.1 localhost 127.0.0.1 processwire 127.0.0.1 mdbnl And after all that just restart apache, put processwire in the right folder and setup from there in it's unique database. Is this all good? Or am I missing a step? Edit: Actually, I tried this, and it seems to work fine, so I guess this is the way to do it I'll leave this up here for anyone who wants to make a second install of processwire on their local Mac environment.1 point
-
Thanks Martijn for the great guide. Just wanted to point out that me and my team have used VirtualHostX for years to make managing multiple local hosts easier. It's a bit pricey, but if you work with a lot of local sites it's a huge time saver. https://clickontyler.com/virtualhostx/1 point
-
If you could only know what they are saying in the background ))) But maybe then this video would not make it's way here or would have been deleted.1 point
-
Hello Marek747 Welcome to the website developers world. You are not the first with exactly these questions. If you go through this forum history you will find real good answers for these questions given by talented coders and experienced web developers. Just look for them. One good thing is that you have found processwire that compared to the other big cms'es out there will save you time in quality and manageable website developing. But to answer some of your questions from my own experience. Becoming a webdeveloper and making money with that is simply not easy in the beginning. It takes time and studying the market. Besides a cms you need to be very good in html, php and css and prototyping a layout that reflects the look and feel for your client and communicate that clear with your client. Many times a client does not have a clear idea of what he wants but makes you responsible if he does not get what he wants. So prototyping until you know what your client exactly wants is important. Also to get payed in case a client decides to change what he wants during the process or in case he wants to cancel the project during the process. That takes time to learn with lots of practise. And that is only halve of it. The other halve is finding projects, planning your time with deadlines, good client communication, getting payed, etc. Don't go for reseller web hosting alone, too much good competition. Better combine making a website including web hosting for your client and make a price for that combination. A good tip is try to work together with an established designer/developer. They usually have lots of work and need a helping hand. It will speed up your learning process drastically. Good luck1 point
-
1) I think you already got enough to start . You will get the rest only doing real things for money with time limits. 2) It depends on how much time do you have. But I am sure you cаn manage 2 per month just cutting your sleep time. 3) I think that you should't worry too much about the right hosting solution for those first small project, Just get anything shared that suits you with some partner program. I used to register individual shared hosting accounts for clients. 4) Why not try freelance sites? There are probably a couple of them in your area (do not know wherе you are). You could offer you services here in the appropriate branch of the forum. 5) I think best way to learn is to go out and try. Just decide what you have to offer and what do you want for it. And then they try to cut it down as much as they can, and you tell them that crafting a site is something bigger than making a word document. Good argument is how much time does it take to do it. 6) It really depends on where you are. I guess you can analize what your competition has to offer and/or try to estimate how long will it take you to do the job. 7) Just start and then you'll know that to do.1 point
-
What about the two times in your code where you do $u->save(), doesn't that save something in DB? Don't think you'll find the issue (apart from that it's something already fixed), as it's quite a complex issue. But if you read the bug report you'll maybe understand, that saving the user will set the language to default for various reasons how the system is built. Maybe you're able to just use the pre 2.5 dev (very stable), or try work around it by setting the user language before saving, but doubt it will work as the issue is on saving a page (users are pages) on front-end using multilanguage.1 point
-
Hats off for that code and thanks for putting the comments. The best captcha I ever saw was a puzzle so easy that even a child could do it, like parking a car with drag and drop, (still) too difficult for (current) captcha breakers.1 point
-
Yes, I saw the video and was also impressed Just want to make sure that a youtube nonstop current of videos doesn't start Or at least that it has it's own place, like the programming (and not only) music thread.1 point
-
@pwired, I know this is the Pub forum... but the PW forums is a cozy place where I really enjoy being away from the wild internet.1 point
-
Super cool new feature just added - well at least I think it's cool You can now automatically backup your entire site's database and templates directory during the import process. Backups are archived so you can go back to any previously created version whenever you want. If something goes wrong during the import phase of the migration, or you simply imported the wrong json file, or you changed your mind, you can restore everything with the click of a button! This database part of this functionality relies on Processwire's brand new WireDatabaseBackup class that Ryan committed today, so to use this functionality, go grab the latest dev version of PW and the latest version of this module. Please let me know how it goes for you!1 point
-
Maybe define it on the init and not ready. Bootstrap doesn't trigger ready as its not web context.1 point
-
but if it has a single image in it, why do you try to select the ->first() ? I assume you have set the image field to allow only 1 image? Also, if you have set it proper to a single image field, it could be that you have a page without an uploaded image to that field. if($featured->Featured_Image) { echo "<img src=\"{$featured->Featured_Image->getThumb('thumbnail')}\" />"; } ------ Also my questions a post above was thought a bit different. I was trying to get you debug the output in your page, just above the line that raises the error. But I wasn't clear, so it doesn't . The error messages said that it isn't an object or the wrong object, so you can debug it to see what's going on. You expect it to be a cropimage field, therefore it should be an instance of type "FieldtypeCropImage". if($featured->Featured_Image->first() instanceof FieldtypeCropImage) { echo "\n<p>the Featured_Image->first() is a cropimage</p>\n"; } if($featured->Featured_Image instanceof FieldtypeCropImage) { echo "\n<p>the Featured_Image is a cropimage</p>\n"; } // imagefield is: FieldtypeImage Most collections in PW are based on WireArrays, so multiple images fields are too and you can look for that: // or checking for single vs multiple if($featured->Featured_Image instanceof WireArray) { echo "\n<p>it is multiple</p>\n"; } else { echo "\n<p>it is single</p>\n"; } You can also just dump a variable with var_dump($featured->Featured_Image->first()) to see what is in it, but that's mostly not very usefull in PW because objects in PW have way to many references to other objects so that var_dump results into very, very large outputs.1 point
-
https://processwire.com/talk/index.php?app=core&module=usercp&tab=core&area=notifications You should be able to configure what you are looking for in the first item?1 point
-
Exactly as you said it, thanks adrian. The fault was entirely my own -- when I couldn't get the relative path working I jumped to the conclusion that the spaces in the filename were causing issues. That, of course, was a dead end. final working code for anyone interested: // do a bunch more stuff $p->save(); echo "saved id:{$p->id} {$p->url}\n"; // add images, y u no store? // Answer: using relative path was wrong (and rawurlencode is unnecessary) // $p->images->add( "./images/" . rawurlencode($row["image"]) ); // get the full server path to processwire, and from there the images $path = $config->paths->root . "test/images/" . $row["image"]; $p->images->add( $path ); $p->save(); Thanks again, Adrian.1 point
-
The full path to the image would be: /home/samplers/public_html/dev/test/images/Best MCC Pic-2.jpg When PHP is doing file operations you need to use the path, as opposed to the URL, which would be: http://dev.domain.com/test/images/Best MCC Pic-2.jpg1 point
-
Joe, I think I read your original post slightly wrong; I thought you meant that there would be a limit on how many pages can be created with each template -- while you probably meant a limit on how many children could each page with given template have. Considering this you can pretty much forget that template part in my first reply.. Also, I said that in ProcessPageAdd you could use "some hard-coded limit or a value of a field in some custom-created setup page (or a custom setting in site config, whichever you prefer) to see if a page can be added below given parent based on the number of existing children." If I'm reading your post correctly now, you'd find the template of the parent page of the page currently being added and get that limit from there, then count existing children for that parent and only then add the page. Makes sense, actually. One more thing I forgot to add to my original reply is that even if you checked in ProcessPageAdd if a page could be added, you'd still definitely want to add additional check at Pages save() just to make sure that two users weren't adding pages at the same time via ProcessPageAdd..1 point
-
I added this to the dev branch last week, so that you can now pass additional things to $page->render(): https://github.com/ryancramerdesign/ProcessWire/blob/dev/wire/modules/PageRender.module#L212 One of the things I wasn't thinking about before is that $page->render() was already capable of accepting an array of options (though not commonly used, mostly internal). So we weren't starting from a blank slate, and had to make something that was compatible and complimentary to what was already there. In terms of API calls, you can now do any of these: $page->render($filename); // $filename assumed in /site/templates/ $page->render($pathname); // $pathname is full path, but must resolve somewhere in web root $page->render($options); // array of options and/or your own variables $page->render(array('foo' => 'bar')); // same as above $page->render($filename, $options); // specify filename and options/vars, etc. The $options variable was already something that $page->render() accepted before. Only it was used to specify some little-used modifiers to render(). Those are still there (and they are necessary), but now the utility of $options has been extended. When you want to specify options (outlined in the link above) you only need to specify the ones you want to change from the defaults (of course). Typically you don't need to change them, so I'm guessing that most would use $options to specify their own variables. Every rendered template now receives a copy of that $options array locally scoped. That $options array contains any variables you passed to $page->render(). It also contains PW's default options, should you want to examine any of them. If you made this render() call: echo $page->render('myfile.php', array('foo' => 'bar')); myfile.php could access the 'foo' variable like this: echo $options['foo']; // outputs "bar" One other addition that I'm thinking people might like is $options['pageStack']. That is an array containing a stack of pages that called render(). So if you are doing any recursive rendering of pages, any template can access $options['pageStack'] to see what page is rendering it, and any others before it. Previously this was not possible, and the only way a template could tell what other page was rendering it (if any) was for that renderer to tell the renderee, via $mypage->caller = $page; or something like that.1 point