Jump to content

Search the Community

Showing results for 'runtime'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Welcome to ProcessWire
    • News & Announcements
    • Showcase
    • Wishlist & Roadmap
  • Community Support
    • Getting Started
    • Tutorials
    • FAQs
    • General Support
    • API & Templates
    • Modules/Plugins
    • Themes and Profiles
    • Multi-Language Support
    • Security
    • Jobs
  • Off Topic
    • Pub
    • Dev Talk

Product Groups

  • Form Builder
  • ProFields
  • ProCache
  • ProMailer
  • Login Register Pro
  • ProDrafts
  • ListerPro
  • ProDevTools
  • Likes
  • Custom Development

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


AIM


MSN


Website URL


ICQ


Yahoo


Jabber


Skype


Location


Interests

  1. haha, i send a virtual coffee to sinnut and ryan . first, i began to code the site with codeigniter, but don't call me a programmer. i like coding and do my best but when i start to follow processwire i thought there is a good idea to migrate the site to it. the reason is because you have an user/role-system, a interface for custom fields, the selector engine and repeaters. before version 2.2 comes bundled with repeaters i tested my data with pages but tend to stay with codeigniter. so far i ended up with the following... it works but the database queries and the other stuff becomes a little bit complicated for me so i wanted to migrate to pw. i downgrade to processwire 2.2.4 with nested repeaters and thought the following screen were a good idea... i think my client like the idea to have the whole information about a book on one page. when i use pages i have a structure like book->runtime->range right? then i could have as many runtime or range pages as possible. thats so far the story
  2. You might try creating a new field using the FieldtypeCache type. This isn't installed by default, but it is included with PW, so you'll just need to click "install" from the modules menu. This field essentially keeps the values from several fields in one field, so that they can all be loaded at once as a group. Like all caches, it's creating duplication and trading disk space for speed. These cache fields are also handy if you are building a text searching engine that needs to scan lots of fields at once... your selector can query just the cache field rather than "field1|field2|field3|etc". Once installed, create the new "cache" field, click to its "details" tab and follow the instructions there. Don't make it autojoin. Instead, have your output generation code reference the cache field field (like $page->my_cache) before any of the others that are triggering queries. This should enable you to reduce it to just one query for all those fields. I'll be honest and say I created this fieldtype with many good intentions, but have rarely found it necessary to use. So be certain the situation you describe really is the bottleneck, and that you aren't omitting pagination or accidentally referencing something like $page->children() or $page/s->find() without a "limit=". The reason that I mention it is that MySQL selects are extremely fast, to the point where the difference between autojoin and non-autojoin may require some scale before you can measure the difference. If you are query counting, avoid doing that, as it often doesn't correlate with performance, especially in ProcessWire. (I used to be a big query counter until I read the book High Performance MySQL, which is reflected in PW's DB query approach). One other idea you might look at is temporarily convincing the fields in question at runtime that they are autojoin, before loading your pages: foreach($selectedFields as $fieldName) { $field = wire('fields')->get($fieldName); $field->flags = $field->flags | Field::flagAutojoin; } That's assuming all the fields in question support autojoin. Some fields, like files/images, can't be autojoined and telling it to may cause unpredictable results.
  3. I love this kind of questions. I think one simple solution would be to have the list of images loaded via ajax (bootstrap PW and return the image array) or render a js object on the album page you will simple use when opening fancybox. Simplest solution for now (other solutions up to others slower posters): Add a link somehwere to the album <a href="#" class="showgallery">Show Gallery</a> The jquery will be like this. $('a.showgallery').fancybox([ {href : 'img1.jpg', title : 'Title'}, {href : 'img2.jpg', title : 'Title'} ], { ..fboptions.. } ); Print that script using php and add the images string on runtime. <?php $imgstr = ''; foreach($images as img) $imgstr .= "{href : '".$img->url."', title : '".$img->description."'},"; ?> $('a.showgallery').fancybox([<?php echo substr($imgstr, 0, -1); ?>], { ..fbconfig.. }); Done. Not tested but you get the idea.
  4. I can't see what fields are in the Range repeater but maybe it's an option to just add a text field to the runtime repeater and just enter the ranges seperated by a delimiter of your choice, so: 1850-1875,1880-1882. You can use explode for front-end purposes. Of course this all depends on your needs. Most of the times when i see nested repeaters is start to wonder if there isn't a better way to structure your content.
  5. i tried to got nested repeaters working and when it fails i read here that ryan closed the option to do this. the problem that i have is that i thought i need nested repeaters but maybe someone have an idea without repeaters. i work on a project about historical books. for example you have 20 sheets of paper of court decisions from berlin between 1850 and 1875 and you have another 100 sheets between 1899 and 1914. that scenario were fine for repeatable fields but now the complex part comes in. the information about the number of sheets can include more than one runtime. for example the 20 sheets above is about the time between 1850-1875 and 1880-1882. now i would need a nested repeater. has someone an idea or can i open the possibility to get nested repeaters working for myself somewhere in the code? thanks a lot... on the screenshot i would like to have the range reapeater into the runtime repeater
  6. $category in this code is a Page object (of Page class) so you can add and populate a property on the fly to the objects and use that on runtime. Like a virtual field that isn't saved to page.
  7. Hi, I loathe forms. Wherever possible I try to avoid implementing them. In this case I have no choice and I'm left with an issue I can't figure out - this is based on Ryan's basic form example. I'm stumped on how to send the check box values to the recipient email. It's probably glaringly obvious to most except me. Regards Marty <?php /** * basic-form.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 = 'email@email.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( 'contact_name' => $sanitizer->text($input->post->contact_name), 'email' => $sanitizer->email($input->post->email), 'comments' => $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 = "<p class='form-error'>Please completed all fields.</p>"; //} //if(empty($form->$company_name)) $error = "<p class='form-error'>Please completed CF field.</p>"; // if no errors, email the form results if(!$error) { $subject = "A message from the contact form"; $message = ''; foreach($form as $key => $value) $message .= "$key: $value\n"; mail($emailTo, $subject, $message, "From: $form[email]"); $sent = true; } } if($sent) { echo "<p>Thank you, your message has been sent.</p>"; // 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" id="contact-form"> <p> <label for="company_name" class="contact_form">Company name:</label> <input type="text" id="company_name" class="contact_form " name="company_name" value="$form[company_name]" size="40" /> </p> <p> <label for="address_1" class="contact_form">Address 1:</label> <input type="text" id="address_1" class="contact_form " name="address_1" value="$form[address_1]" size="40" /> </p> <p> <label for="address_2" class="contact_form">Address 2:</label> <input type="text" id="address_2" class="contact_form " name="address_2" value="$form[address_2]" size="40" /> </p> <p> <label for="suburb" class="contact_form">Suburb</label> <input type="text" id="suburb" class="contact_form " name="suburb" value="$form[suburb]" size="40" /> </p> <p> <label for="state" class="contact_form">State:</label> <input type="text" id="suburb" class="contact_form " name="state" value="$form[state]" size="20" /> </p> <p> <label for="postcode" class="contact_form">Postcode:</label> <input type="text" id="postcode" class="contact_form " name="postcode" value="$form[postcode]" size="10" /> </p> <p> <label for="country" class="contact_form">Country:</label> <input type="text" id="postcode" class="contact_form " name="country" value="$form[country]" size="40" /> </p> <p> <label class="contact_form" for="contact_name">Contact person:*</label> <input class="contact_form required" type="text" id="contact_name" name="contact_name" size="40" value="$form[contact_name]" /> </p> <p> <label for="position" class="contact_form">Position:</label> <input type="text" id="position" class="contact_form " name="position" value="$form[position]" size="40" /> </p> <p> <label for="phone" class="contact_form">Phone</label> <input type="text" id="phone" class="contact_form " name="phone" value="$form[phone]" size="40" /> </p> <p> <label class="contact_form" for="email">Your email:*</label> <input class="contact_form required" type="email" name="email" id="email" size="40" value="$form[email]" /> </p> <fieldset class="products"> <p>Products of interest:</p> <fieldset class="prod_col"> <input type="checkbox" id="Hats" name="Hats" value="$form[hats]" /><label for="Hats" class="Hats">Hats</label><br/> <input type="checkbox" id="Gloves" name="Gloves" value="$form[gloves]" /><label for="Gloves" class="Gloves">Gloves</label><br/> <input type="checkbox" id="Mens" name="Mens" value="$form[mens]" /><label for="Mens" class="Mens">Mens</label><br/> </fieldset> <fieldset class="prod_col"> <input type="checkbox" id="Bags" name="Bags" value="$form[bags]" /><label for="Bags" class="Bags">Bags</label><br/> <input type="checkbox" id="Scarves" name="Scarves" value="$form[scarves]" /><label for="Scarves" class="Scarves">Scarves</label><br/> <input type="checkbox" id="Clothing" name="Clothing" value="$form[clothing]" /><label for="Clothing" class="Clothing">Clothing</label><br/> </fieldset> </fieldset> <p> <label class="contact_form comments" for="comments">If you have any further comments or questions, please complete this area:</label> <textarea class="contact_form" id="comments" name="comments" rows="5" cols="62">$form[comments]</textarea> </p> <input class="contact_submit" type="submit" name="submit" value="Submit" /> <p>* required fields</p> </form> _OUT; } ?>
  8. Yeah, permissions and ownership look OK. The folder is accessible just fine without .htaccess. Here is the full file: ################################################################################################# # START PROCESSWIRE HTACCESS DIRECTIVES # @version 2.1 ################################################################################################# # ----------------------------------------------------------------------------------------------- # Don't show directory indexes, but do follow symbolic links # ----------------------------------------------------------------------------------------------- Options -Indexes Options +FollowSymLinks # ----------------------------------------------------------------------------------------------- # Let ProcessWire handle 404s # ----------------------------------------------------------------------------------------------- ErrorDocument 404 /index.php # ----------------------------------------------------------------------------------------------- # Handle request for missing favicon.ico/robots.txt files (no ending quote for Apache 1.3) # ----------------------------------------------------------------------------------------------- <Files favicon.ico> ErrorDocument 404 "The requested file favicon.ico was not found. </Files> <Files robots.txt> ErrorDocument 404 "The requested file robots.txt was not found. </Files> # ----------------------------------------------------------------------------------------------- # Protect ProcessWire system files (part 1) # ----------------------------------------------------------------------------------------------- <FilesMatch "\.(inc|info|module|sh|sql)$|^(\..*)$"> Order allow,deny </FilesMatch> # ----------------------------------------------------------------------------------------------- # Override a few PHP settings that can't be changed at runtime (not required) # ----------------------------------------------------------------------------------------------- <IfModule mod_php5.c> php_flag magic_quotes_gpc off php_flag magic_quotes_sybase off php_flag register_globals off </IfModule> # ----------------------------------------------------------------------------------------------- # Set default directory index files # ----------------------------------------------------------------------------------------------- DirectoryIndex index.php index.html index.htm # ----------------------------------------------------------------------------------------------- # ProcessWire requires mod_rewrite # ----------------------------------------------------------------------------------------------- <IfModule mod_rewrite.c> RewriteEngine On # ----------------------------------------------------------------------------------------------- # Set an environment variable so the installer can detect that mod_rewrite is active. # ----------------------------------------------------------------------------------------------- SetEnv HTTP_MOD_REWRITE On # ----------------------------------------------------------------------------------------------- # Optional: Set a rewrite base if rewrites aern't working properly on your server. # And if your site directory starts with a "~" you will most likely have to use this. # ----------------------------------------------------------------------------------------------- # RewriteBase / # RewriteBase /pw/ # RewriteBase /~blah/ # ----------------------------------------------------------------------------------------------- # Access Restrictions: Keep web users out of dirs that begin with a period # ----------------------------------------------------------------------------------------------- RewriteRule "(^|/)\." - [F] # ----------------------------------------------------------------------------------------------- # Optional: Redirect users to the 'www.' version of the site (uncomment to enable). # For example: http://processwire.com/ would be redirected to http://www.processwire.com/ # ----------------------------------------------------------------------------------------------- RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # ----------------------------------------------------------------------------------------------- # Access Restrictions: Protect ProcessWire system files (part 2) # ----------------------------------------------------------------------------------------------- RewriteCond %{REQUEST_URI} (^|/)\.htaccess$ [NC,OR] RewriteCond %{REQUEST_URI} (^|/)site/assets/(cache|logs|backups|sessions|config|install)($|/.*$) [OR] RewriteCond %{REQUEST_URI} (^|/)site/install($|/.*$) [OR] RewriteCond %{REQUEST_URI} (^|/)site/config\.php$ [OR] RewriteCond %{REQUEST_URI} (^|/)(wire|site)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ [OR] RewriteCond %{REQUEST_URI} (^|/)site/templates($|/|/.*\.(php|html?|tpl|inc))$ [OR] RewriteCond %{REQUEST_URI} (^|/)site/assets($|/|/.*\.php)$ [OR] RewriteCond %{REQUEST_URI} (^|/)wire/(core|modules)/.*\.(php|inc|tpl|module)$ [OR] RewriteCond %{REQUEST_URI} (^|/)site/modules/.*\.(php|inc|tpl|module)$ [OR] RewriteCond %{REQUEST_URI} (^|/)(COPYRIGHT|INSTALL|README|htaccess)\.txt$ [OR] RewriteCond %{REQUEST_URI} (^|/)site-default/ RewriteRule ^.*$ - [F,L] # ----------------------------------------------------------------------------------------------- # Ensure that the URL follows the name-format specification required by ProcessWire # ----------------------------------------------------------------------------------------------- RewriteCond %{REQUEST_URI} "^/~?[-_.a-zA-Z0-9/]*$" # ----------------------------------------------------------------------------------------------- # If the request is for a file or directory that physically exists on the server, # then don't give control to ProcessWire, and instead load the file # ----------------------------------------------------------------------------------------------- RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !(favicon\.ico|robots\.txt) # ----------------------------------------------------------------------------------------------- # Optional: Don't send missing image requests to ProcessWire (uncomment below to enable). # This might be helpful if you are launching a new site and lots of images have moved. # It will reduce the load on the server not to have ProcessWire trying to serve those requests. # ----------------------------------------------------------------------------------------------- # RewriteCond %{REQUEST_URI} !\.(gif|jpg|png|ico)$ [NC] # ----------------------------------------------------------------------------------------------- # Pass control to ProcessWire if all the above directives allow us to this point. # For regular VirtualHosts (most installs) # ----------------------------------------------------------------------------------------------- RewriteRule ^(.*)$ index.php?it=$1 [L,QSA] # ----------------------------------------------------------------------------------------------- # If using VirtualDocumentRoot: comment out the one above and use this one instead. # ----------------------------------------------------------------------------------------------- # RewriteRule ^(.*)$ /index.php?it=$1 [L,QSA] </IfModule> ################################################################################################# # END PROCESSWIRE HTACCESS DIRECTIVES #################################################################################################
  9. Hi Pete, Many thanks for responding! I don't think I made myself clear. What I was referring to was caching the runtime results of queries, not their definitions, and possibly HTML fragments (generated on the fly) that might be used more than once in the same server-side hit. Know what I mean? Cheers --Gary
  10. I use the .less apps http://incident57.com/less/ (mac, pc also is available elsewhere), that converts to regular CSS when saving (watching files), you can also set it to minify them. I'm not a fan of serverside or js runtime. It's basicly great tool to help using variables and mixins etc to write css.
  11. What do you want to debug? I have to say I have no clue about PHPStorm and XDebug. I think this has not much to do with PW rather than your IDE and PHP. DO you mean a local runtime environement? I think without having PW context there (not plain php) it doesn't really make sense, and something you do while coding templates -> testing in browser, if error go back and check, fix, continue. There's also debug option you can enable in /site/config.php to see errors and warnings. Edit: I think your struggle is also little selfmade, I've never needed autocomplete for something like PW, or debug, lint or anything, just for coding php websites, rarely really have the need as it's so simple. What I sometimes use is a phplint to spot errors in php code right away, but mostly it's just annoying and slows IDE's down.
  12. Hello there! Appreciation First of all I would like to say Thank You for making such a fantastic back-end. In my ten years of web development it's the first one to actually make sense to me. When I used to develop in Flash I was searching every where for a back-end that would just let me output my data as xml without the hassle of learning a new "language" or syntax, or messing with settings directly in the back-end itself. For my current portfolio and some other sites I ended up using Drupal with some plugins for managing the data and then just dug in to the database directly, pulling out whatever i needed. It wasn't easy, but it was easier than learning how to make an actual plugin that did the same. With process wire I realize now I could have saved weeks of development, had I known of it's existence. It was so easy to get into that I basically just sad down a few hours one day to get familiar with the UI and I have only had use for the cheat sheet ever since. This stuff is build in a very logical way and without unneeded complexity. I can see a lot of thought / experience has gone into this, and I really appreciate you letting us use it! Question I have some ideas for new modules that I would like to build. They would add some extra functionality to the core functions of Processwire. One is to implement getID3() (http://getid3.sourceforge.net/) to get the extra data in mp3s like $fileMp3->composer for example. The other one is to add extra image functionality on both the front- and back-end using imagemagick. I'm updating my portfolio to an html5 version and it's going to have a worn down/outdoor look, and therefore I'd like to add some Instagram type of effects to certain images (http://net.tutsplus....lters-with-php/). On the back-end I would like to add options for adding image effects when the image has been uploaded. I would like to keep the original while the modified Image is used by the front-end. Ideally it would be a drop down with some predefined effects while having the option to add more than one effect. Next would be to extend the Image with more options, just in the same way resize works. For example $fileImage->resize(150,150)->kelvin(75, "#4499ff") I'll post what I came up with so far. It's inspired mainly by the tutsplus article and it contains obvious errors, but it's more to give you an idea of what I want to achieve. I looked for an Image class to add a hook to - in the same way that resize works, but I couldn't really find out how it was put together. I also don't quite understand why this module shows up under an "Image" section as I didn't define it anywhere (see attached image). I'm not asking for finished code here, but looking for guidance as http://processwire.com/api/modules/ and the hello_world.module don't tell me what I want to know. Or maybe I'm looking in the wrong place? Anyway, here's the code so far. Any tips would be greatly appreciated! ( And sorry for the wall of text ) <?php class ImageInstagram extends WireData implements Module { public $_image = NULL; public $_output = NULL; public $_prefix = 'IMG'; private $_width = NULL; private $_height = NULL; private $_tmp = NULL; public static function getModuleInfo() { return array( // The module'ss title, typically a little more descriptive than the class name 'title' => 'Image Instagram Effects', // version: major, minor, revision, i.e. 100 = 1.0.0 'version' => 003, // summary is brief description of what this module is 'summary' => 'Add InstaGram effects to images', // Optional URL to more information about the module 'href' => 'http://www.processwire.com', // 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, ); } public function init() { $this->addHook('Images::kelvin', $this, 'kelvin'); } public function kelvin($event) { $this->tempfile(); $this->execute("convert( $this->_tmp -auto-gamma -modulate 120,50,100 ) ( -size {$this->_width}x{$this->_height} -fill 'rgba(255,153,0,0.5)' -draw 'rectangle 0,0 {$this->_width},{$this->_height}' ) -compose multiply $this->_tmp"); $this->frame($this->_tmp, __FUNCTION__); $this->output(); } public function tempfile() { # copy original file and assign temporary name $this->_tmp = $this->_prefix . rand(); copy($this->_image, $this->_tmp); } public function frame($input, $frame) { $this->execute("convert $input ( '$frame' -resize {$this->_width}x{$this->_height}! -unsharp 1.5×1.0+1.5+0.02 ) -flatten $input"); } public function execute($command) { # remove newlines and convert single quotes to double to prevent errors $command = str_replace(array("\n", "'"), array('', '"'), $command); $command = escapeshellcmd($command); # execute convert program exec($command); } public function output() { # rename working temporary file to output filename rename($this->_tmp, $this->_output); } }
  13. Because when PW presents you with an upload field, it wants to know where the file is going to go. There's more to it than that too. Every page has an optional delegate object called a PagefilesManager. That class manages all disk-based files for a Page and it doesn't know anything about who's using it (whether a Fieldtype, Inputfield, API access, etc.). This is a good thing. And it's only called on demand. But when it's called, it makes sure there is a place for that page on the drive. Ultimately, it's not just having an file/image field that causes the directory to be created, it's the actual calling upon the file/image field, which ensures they have a home. A prerequisite for a file-based asset is a place to put it. This limits the dependencies and complexity between these systems and it's the way I think it should be. They could be, but that's trading processor time for disk space. Disk space is cheaper. I also think that if you are putting file/image fields on huge quantities of pages that don't need them, you are adding unnecessary overhead to runtime that's a far bigger affect to performance than some empty directories on your server. If you've got tens of thousands of pages with file fields on them that you edit in the admin, and you don't want them to have directories, then run the new empty dirs module once in awhile.
  14. I think these are good ideas. Regarding the quality setting: ImageSizer does support adjustment of the quality (via the setQuality() method), but there's not currently a way to get directly to that from the size(), width() or height() functions (like with the upscaling option). However, I'm wondering if this is something that needs to be on-the-fly or might be better off in a $config setting that you can set for the whole site? (or modify it at runtime as needed). Something like this: // just an idea, but not yet implemented, so don't put in your config.php yet $config->imageSizerQuality = 90; $config->imageSizerUpscaling = false; $config->imageSizerCropping = true; Of course, that could still be on-the-fly, by modifying the $config properties at runtime. But just wondering if this might be better than adding params to functions that most won't need to utilize. In addition, we could always provide a 3rd param $options array to the size() function that could override individual settings too, but wouldn't want to make that the only way since I'm guessing most don't need to set these things but once. Regarding the crop, I like the idea and capability. I just don't know how to do it, yet. If anyone wants to collaborate I'd love to get the capability in there. Rather than getting it in as another function param, I'd want to integrate that option as part of the $options array to the function, i.e. $image->size(100, 100, array('position' => 'top-left', 'quality' => 95));
  15. If I understand correctly, you want to change the rendering context at runtime if certain conditions are met. You have a few options. 1. You could set your $video to have a different template file before calling $video->render(); /site/templates/home.php $video->template->filename = 'teaser.php'; echo $video->render(); 2. Or you could throw up a flag that your video.php template file knows to look for: /site/templates/home.php $input->whitelist('teaser', 1); echo $video->render(); …and in your video.php: /site/templates/video.php if($input->whitelist('teaser')) { include('teaser.php'); } else { // render full video page } The advantage here is that all your video rendering code is together in one file. 3. Or you could include your teaser.php from home.php manually: /site/templates/home.php $_page = $page; $page = $video; // substitute $page before including teaser.php include('./teaser.php'); $page = $_page; // return $page to it's original state 4. Or you could isolate the teaser rendering to a function (perhaps included from another file): /site/templates/functions.inc function renderTeaser($page) { return "<p><a href='{$page->url}'>{$page->title</a><br />{$page->summary}</p>"; } /site/templates/home.php include('./functions.inc'); echo renderTeaser($video); This last option is the one I'd be most likely to take as I think it's probably one of the lowest overhead, it's easily reusable across different templates, and requires very little consideration wherever you use it. Here's another way you can do the same thing, by actually adding a renderTeaser() function to the Page class at runtime: /site/templates/functions.inc function renderTeaser(HookEvent $event) { $page = $event->object; $event->return = "<p><a href='{$page->url}'>{$page->title</a><br />{$page->summary}</p>"; } $this->addHook('Page::renderTeaser', null, 'renderTeaser'); And now you can do this: echo $video->renderTeaser(); Btw that line that has $this->addHook(); has null as the 2nd argument because the function is outside of a class. Some people create auto-loading modules to contain rendering functions, in which case that 2nd argument is the module's object instance.
  16. A example code how to set a templatefile on runtime $t = new TemplateFile($config->paths->templates . "./another.php"); // send vars explicitly possible // $t->set( "somevar", $somevar ); // $t->set( 'input', $input); echo $t->render(); However I think you might like the template option i the advanced setting to use another template instead. Also your example works using the render method of a page. Have a template video.php that includes teaser.php. Then use your example code as is.
  17. Thanks arjen. I prefer the rewrites directly on apache because it's faster / uses less resources. A new version from PW is not a problem for me, because i don't touch the original. While deploying to live server, a shell script automatically prepends my additions to it. -- OFF-TOPIC -- Maybe someone is interested, i'll explain it in detail: - I store my projects in private git repositories on bitbucket.org - I have environment variables on my local machine, so I can differentiate in config.php which config is needed on runtime (like database, debug mode...). That allows me to have one version of the project which auomatically runs on live and development server - when i want to do a live or preview update, i just start a shell script which: 1. creates a fresh clone of the repository in a subdirectory like "live-2012-06-28" 2. if needed, it sets chown and chmod for caching directories 3. it compresses my javascript and css files with yui-compressor (my environment switch will print out minified in live and normal scripts in development) 4. it checks for htaccess-extra files, which then get prepended or appended to the original .htaccess (like redirects, expires) 5. the docroot is not a folder, it's a symlink. final step is to set the symlink to the new updated folder And thats it. I can make changes in my code without touching the PW core, push everything to git, and run the update script to deploy everything. If something goes wrong, I only have to reset the symlink to the previous version folder. A second script does nearly the same, but instead deploying live it depoys to a preview subdomain. So i can check my changes on the live server environment first, before destroying the live
  18. Awesome feature! I hope it's a 301, not a 302 Does this happen while dispatching or do you modify the .htaccess on runtime?
  19. Cufon essentially makes the words using a font as PNG images at runtime, whereas Fontsquirrel and others simply use actual font files, using CSS to present various file types depending on the browser being used. Looking forward to the new version but no rush.
  20. The reason those options don't appear if the cache time is set to 0 is because 'cache time' is not just a time, but also a toggle. When non-zero, cache is enabled. When zero, cache is not enabled. When cache is not enabled, none of the cache options are even considered by ProcessWire. But if you want to bypass ProcessWire's cache settings at runtime, you can do so. For example, you could use the 'URL pre-segment' approach, enable the cache, and disable it manually before rendering the page: $mypage = $pages->get($path); $mypage->template->cache_time = 0; // disable the cache echo $mypage->render();
  21. The PageLinkAbstractor is also a 3rd party module, and not one that I would try to build around at all. If something doesn't work with that module, then I would just say the two are not compatible with each other. I don't think many people are actually using that PageLinkAbstractor module anyway. I don't personally use it. If I've been developing a site in a subdirectory and then launch it to the root on another server, I just do a simple search+replace on the DB dump file, using a text editor (TextWrangler/BBEdit) replacing "/subdirectory/" with "/". However, this is something that I do plan to add core support for. The plan is that FieldtypeTextarea will encode local links to IDs like {123} when saving, and then unencode them back to URLs at runtime. We can collaborate on making everything work together when the time comes. I think I understand the problem you mentioned with a link created in TinyMCE being a static link in the language of the user making the edit. Would it be possible to just disable the URL parsing when the user is inserting a link? if(wire('process') == 'ProcessPageEditLink') { // don't parse URLs } else { // do parse URLs } The point of the above is so that the URL is always stored in the default language. Then hook into FieldtypeTextarea::formatValue and have it hunt down and replace them with the current language specific version, at runtime. I'm not so familiar with how the language localized URL module works, so this is based on guesses, but it might work something like this: public function init() { $this->addHookAfter('FieldtypeTextarea::formatValue', $this, 'hookFormatValue'); } public function hookFormatValue(HookEvent $event) { $language = wire('user')->language; // no need to continue if user's language is default if($language->isDefault()) return; $page = $event->arguments[0]; // not using, but here if you need it $field = $event->arguments[1]; // not using, but here if you need it $value = $event->arguments[2]; $rootUrl = rtrim(wire('config')->urls->root, '/'); // find links if(!preg_match_all('{href=[\'"]([-_./a-z0-9]+)}[\'"]', $value, $matches)) return; foreach($matches[1] as $key => $url) { // slice off subdirectory if site is running from one, so we have a clean URL from PW-install root if($rootUrl && strpos($url, $rootUrl) === 0) $url = substr($url, strlen($rootUrl)); // see if this is a link to a PW-managed page in the site $linkPage = wire('pages')->get($url); if(!$linkPage->id) continue; // now that you have the $linkPage and know the $language you should be able to // get the language URL right? I don't know how you do it, so I'll pretend: $langUrl = $this->getLanguageUrl($linkPage, $language); // replace the default language URL with the language URL $value = str_replace($matches[0][$key], "href='$langUrl'", $value); } $event->return = $value; }
  22. Something that is storing images exclusively on another server probably needs to be a different animal from the existing image/file fieldtypes. Rather than trying to hook into functionality there, I would go and create a new fieldtype so you can start fresh. On the other hand, if the goal is to just keep a copy of any files used at the other server, and then replace references to them at runtime (like when output formatting is on or something) then I think that would be more of a scenario where hooks would be useful.
  23. @diogo Thanks for sharing your code. I just packed it in a Module adding some features. It extends the Page class, by hooking a new method mlUrl(bool includePageId). I wanted to generate the localized url too. So instead of using names I use title to generate url. That function accepts one boolean parameter to specify if to use the page id: www.mydomain.com/it/my-italian-title/ www.mydomain.com/it/[page id]_my-italian-title The id is useful if you can't be sure that the localized title is unique, or in case that there are a lot of contents and you don't want to search by title in a long loop, but seeking directly by id. The generated url always contains the language code, for the default one too, that in this case is manually mapped to 'en'; This is the code (that could be improved, especially in the generation of the url): <?php class MultiLanguageURL 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' => 'MultiLanguageURL', // version: major, minor, revision, i.e. 100 = 1.0.0 'version' => 100, // summary is brief description of what this module is 'summary' => 'Multi language url', // Optional URL to more information about the module 'href' => '', // 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, ); } /** * Initialize the module * * ProcessWire calls this when the module is loaded. For 'autoload' modules, this will be called * when ProcessWire's API is ready. As a result, this is a good place to attach hooks. * */ public function init() { $this->addHook('Page::mlUrl', $this, 'mlUrl'); } private function mlPath($page) { if($page->id === 1) return '/'; $path = ''; $parents = $page->parents(); foreach($parents as $parent) if($parent->id > 1) $path .= "/".$this->toSlug($parent->title); return $path . '/' . $this->toSlug($page->title) . '/'; } public function mlUrl($event) { $page = $event->object; $includeId = $event->arguments(0); $url = $this->mlPath($page); if ($includeId) { $segments = explode('/', $url); $index = count($segments)-2; $segments[$index] = $page->id.'_'.$segments[$index]; $url = implode('/', $segments); } $lang = $this->user->language->name; if (!$lang || $lang=='default') $lang = 'en'; $event->return = '/'.$lang.$url; } private function toSlug($str) { $str = strtolower(trim($str)); $str = preg_replace('/[^a-z0-9-]/', '-', $str); $str = preg_replace('/-+/', "-", $str); return $str; } public function parseUrl() { $page = $this->fuel('page'); $user = $this->fuel('user'); $languages = $this->fuel('languages'); $pages = $this->fuel('pages'); $input = $this->fuel('input'); $lang = $page->name; if ($lang == 'en') $lang='default'; $user->language = $languages->get($lang); $basePage = $pages->get("/"); $segments = $input->urlSegments; if($segments){ $page = $basePage; foreach($segments as $segment){ // search of page id inside the segment $parts = explode('_', $segment); $pageid=null; if (count($parts)>1 && is_numeric($parts[0])) { $pageid=$parts[0]; $page = $pages->get($pageid); } else { $children = $page->children; foreach ($children as $child){ $found = false; if($segment==$this->toSlug($child->title)){ $page = $child; $found = true; break; } } } if (!$found) throw new Wire404Exception(); } } else { $page = $basePage; } $this->fuel->set('page', $page); return $page; } } This is the code to use the module in your template: <?php $page = $modules->get('MultiLanguageURL')->parseUrl(); include("./{$page->template}.php"); ?> and to generate the localized url: // to include the page id $page->mlUrl(true); // to generate without id $page->mlUrl(false);
  24. Hey Ryan, thanks! How is the selector supposed to look like? created_users_id=1009|modified_users_id=1009 produces the same result as above (like where created_users_id=1009 AND modified_users_id=1009) created_users_id|modified_users_id=1009 seems to skrew up everything (identically for all results without filter) edit: Not true, generates the same as above. Problem is: I have a more complex environment which also produces weird results when I set a get('/') before filtering. This is the code, I hope it is not too weird, PHP skills are a bit rusty (if ever existed): <?php /** * ProcessWire 'Hello world' demonstration module * * Demonstrates the Module interface and how to add hooks. * * ProcessWire 2.x * Copyright (C) 2010 by Ryan Cramer * Licensed under GNU/GPL v2, see LICENSE.TXT * * http://www.processwire.com * http://www.ryancramer.com * */ class WidgetListPages extends Widget { /** * 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' => 'ListPages Widget', // version: major, minor, revision, i.e. 100 = 1.0.0 'version' => 001, // summary is brief description of what this module is 'summary' => 'Widget which shows pages in a table with optional edit and view buttons.', // singular=true: indicates that only one instance of the module is allowed. // This is usually what you want for modules that attach hooks. 'singular' => false, // 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, ); } public function __construct() { $this->set('sortby', '-created'); $this->set('parentid','/'); $this->set('limit', 10); $this->set('lable', 'title'); $this->set('ownCreated', false); $this->set('ownModified', false); $this->set('restriction', 'page-edit'); $this->set('createNew', false); $this->set('createNewLabel', $this->_('Create new page here')); $this->set('createNewParent', $this->parent); } public function init(){ } public function render(){ $adminUrl = $this->config->urls->admin; $this->filter = 'sort='.$this->sortby.','; $table = $this->modules->get("MarkupAdminDataTable"); $table->setEncodeEntities(false); //show only documents of viewing user if($this->ownCreated===true && $this->ownModified===true){ $this->filter.='created_users_id|modified_users_id=' . $this->user->id . ','; } else { if($this->ownCreated===true) $this->filter.='created_users_id=' . $this->user->id . ','; if($this->ownModified===true) $this->filter.='modified_users_id=' . $this->user->id . ','; } //debug echo $this->filter.'<br>'; // this is the next weird thing: If I apply a parent some pages are missing (the ones directly under the root) $res = wire('pages')->get($this->parentid)->find($this->filter); foreach ($res as $result){ //$output .= $result->title.'<br>'; $table->row(array('<a href="'.$adminUrl.'page/edit/?id='.$result->id.'">'.$result->title.'</a>',$result->modified)); } // apply create new page button? if($this->createNew){ $button = $this->modules->get("InputfieldButton"); $button->type = 'submit'; $button->id = 'submit_new'; $button->value = $this->createNewLabel; $table->action(array('create New' => $adminUrl.'page/add/?parent_id='.$this->createNewParent)); } $this->content = $table->render(); $out = $this->renderWidget(); return $out; } } Sorry for just pasting it, but have to go now. Perhaps you see something I totally miss (probably )
  25. Hey marc, as Ryan already stated, changing this core functionality would require A LOT of changes, additional complexity... The ___path function of pages is certainly hookable and possible to rewrite urls, but then you'll have not resolving urls, and the journey continues. You'll certainly run into problems not being able to pull it off because it can't be done or has side effects. As suggested using mutliple trees is the most slim solution. I'm thinking about this subject a long time, and refused to really ask for such a feature because I knew Ryan's answer already. All projects I did at work are multilingual and I solved it always using multiple trees. It makes a lot of thing easier and you doesn't need to consider "will this work here" and start fighting the system. Also you are flexible as much as possible. What I additionally tend to do, is to use "central" content where it makes sense (properties), that's put outside the language tree and then use urlSegments and the language information, to pull the content and display. Urls set in TinyMCE can also be parsed by a runtime hook after Page::render, you then search for certain url structure and replace it with the one you need. I've also done it with simple sections for a online shop (bag-shop.ch) where the products are outside the language tree and the collection page just renders them and product urls get rewritten using the hook technique described above.
×
×
  • Create New...