Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 12/06/2014 in all areas

  1. So, let's launch this finally! › https://processwire-recipes.com/ ‹ As you can see, it's a work in progress. The design is going to change, Nico at the helm, and once we got a "critical mass" of recipes, another way of structuring recipes (the "table of contents") will also go online. To contribute, you can post your recipes either in this thread and we'll pick it up, or - codey - via Pull Request on GitHub of this repo here. Frankly, that's the favoured way, simple and a good start dive in to GitHub and this form of Open Source contribution. As always, feedback (and of course, contribution) is really welcome. We're always eager to learn - and helping to learn new stuff and create a place to spread some PW knowledge, that's what PWR was about in the first place Big big thanks to my partner in crime owzim who, among other things, contributed the - imho - heart of this tiny project: a textfile-to-page-importer. Finding an elegant way to contribute was one of the reasons this took so long, and during Beyond Tellerrand conference, it finally clicked into place.
    11 points
  2. It would be great if the wireMail function could be used for sending emails instead of the php mail function. This way people would be able to use it together with their favourite mail extensions. For example with SMTP support: wiremail-swiftmailer or wiremailsmtp
    3 points
  3. It struck me today, as I was working on a large site, that it would be really nice if the Setup -> Fields fly-out menu would implement the "Tags" feature to group fields into sub-menus. I use Tags (defined under the 'Advanced' tab when editing a field) to neatly organize fields on the actual Setup->Fields page. It would be great if the menu was also organized the same way. A single fly-out menu of 50+ un-grouped fields isn't so useful... What do you think?
    3 points
  4. I have an as yet undocumented update to this module that will do that. Here is the most current version ProcessRedirects.zip I've been using this version on a high traffic site for over a month, and it's solid. You may have to use 2 rules (depending on what you want) The * at the end is a wildcard.
    3 points
  5. Hello there, ProcessWire has been the perfect CMS for me so far but I always missed the Laravel way of doing things when working with PW. Therefore I've built a package that will integrate Laravel into ProcessWire. It's already working out really well and I can imagine a lot of stuff to come in future. Anyways I'm hoping for some peoples support / pull requests / ideas / opinions ... Here's the link: https://github.com/hettiger/larawire Enjoy!
    2 points
  6. exactly! You can call size() with second param = 0 (zero), what is the same as calling width(). Pageimage::size build the names according to passed values for width, height and optional options for cropping and suffix: basename.widthxheight-suffix.ext and the code of the function for blog images should be look like that, because there is no $event->arguments(2) available like it could be when calling from templatecode: public function sizeBlogCloud($event) { $image = $event->object->getPageImage(); $width = (int) $this->input->get->width;//$event->arguments(0); // $height = (int) $this->input->get->height; //$event->arguments(1); // not needed here, or set it to 0 $options = array(); if ($width < $image->width) { // add a suffix if it is a resized version, don't add a suffix if it is the original unresized image $options["suffix"] = array("is"); } $resized = $image->size($width, 0, $options);
    2 points
  7. great! What i really would like (and i know that owzim and you think about that topics!!) is voting/starring a recipe... may be this module from conclurer (Marvin and Phillip) https://processwire.com/talk/topic/7871-page-ratings/ or fieldtyp starrating: https://processwire.com/talk/topic/4561-fieldtyperate-star-rating/ regards mr-fan
    2 points
  8. Thanks for your contribution, mr fan, we'll include in after we finished small adjustments in the recipes structure. In other news, you can now subscribe to new recipes via RSS or Twitter.
    2 points
  9. Finally found time so rewrite the thing. In short, it is now working but I can't figure out what didn't work before. 1) My $size was set to 0. This was my mistake. The width() options just ignored the $options array. 2) I manually removed all pages including the image files and re-upload them. This made PIM PageImage objects work as well as the ProcessWire ones. Sorry, this seems like a fault on my side. PIM works fine once you get the things around right.
    2 points
  10. Great in lack of time i post here some links with description: 1. adrian - copy page via api https://processwire.com/talk/topic/7101-easy-way-to-clone-a-page-from-api/#entry68465 2. harmster - using csrf in own forms https://processwire.com/talk/topic/3779-use-csrf-in-your-own-forms/ 3.horst - implement a global ultility function lib/file https://processwire.com/talk/topic/7573-best-way-to-implement-a-global-utility-function/#entry73157 4. nico - reset password via api https://processwire.com/talk/topic/7167-server-error-with-latest-dev-build/#entry69041 5. yellowled - list/filter items https://processwire.com/talk/topic/7673-list-items-or-contacts/#entry74444 for the moment - i will catch the repo until i've the time....it's christmas you know for most germans this not really a quiet time....
    2 points
  11. Well, I’ll give you a short example to demonstrate how it all works together. Imagine the following simple setup: Page Tree Home |- Products (template=products) | |- Product 1 (template=product) | |- Product 2 | |- Product 3 | |- Product 4 | |- Product 5 | |- ... Page Products with template “products” is meant to show a gallery of product images. So we create a controller for the template (that otherwise would be auto-generated on the fly) in site/templates/controllers/ named products.controller.php. <?php /* site/templates/controllers/products.controller.php */ class ProductsController extends BaseController { // init() is executed on controller setup before action is called public function init() { // Just in case you defined general stuff in BaseController’s init() method parent::init(); // Set (for all actions of this controller) a script 'jquery/my.jquery.plugin.js' in group 'footer' with priority 5 // In layout and template you can then output the scripts group 'footer' using view helper <?=scripts('footer');?> // Assets defined via path are looked up in the corresponding folder within site/templates/assets/. You can alternatively // define assets using a URL. $this->script('jquery/my.jquery.plugin.js', 'footer', 5); } // index is the default action executed if no other route matches public function index() { // Add (for this action only) a stylesheet 'gallery.css' to group 'footer' with priority 10. // In layout and template you can then output the styles group using view helper <?=styles('footer');?> $this->style('gallery.css', 'footer', 10); // Set a template var 'products' that contains current page’s children as PageArray $this->set('products', $this->page->children('template=product, sort=title')); } } We’ll need an action template for products’ index action in site/templates/views/products/ named index.tmpl.php. <!-- site/templates/views/products/index.tmpl.php --> <h2><?=$title?></h2> <ul class="products"> <?php foreach($products as $product) { ?> <li class="products__item <?=gridClass($product->images->first(), 'products__image');?>"><a href="<?=$product->url?>"><img src="<?=$product->images->first()->url;?>" alt="<?=$product->title;?>"></a></li> <?php } ?> </ul> We’ll have a look at the used view helper gridClass() later. The first page in PW’s page stack (the one rendered through processPageView directly) is rendered and outputted in a layout’s outlet. Layouts are stored in site/templates/layouts. There is a default layout default.tmpl.php preinstalled. The rendered action templates are outputted within the document structure by using <?=$outlet?>. You can add as many layouts as you want and change the layout the action template will be rendered in by setting another template within your controller’s init() method like this: ... public function init() { parent::init(); // use layout site/templates/layouts/shop.tmpl.php for this template $this->set('layout', 'shop'); } ... Our product template of course also gets a controller: <?php /* site/templates/controllers/product.controller.php */ class ProductController extends BaseController { public function init() { parent::init(); // assign route pattern with dynamic segment to action 'reviewVote' $this->route('/reviews/:id/vote/', array('id' => '^[0-9]+$'), 'reviewsVote'); } public function index() { // set dynamic value to be calculated right before rendering the action template $this->set('similarProducts', function() { // your logic to get a PageArray of similar products goes here $tags = $this->page->get('tags'); // or $tags = $this->get('tags'); as it will pass the request through to page, if 'tags' isn’t set on controller itself $similarProducts = ...; return $similarProducts; }); } // action accessible via route /reviews/ public function reviews() { // we should set up this for pagination in template settings $this->set('reviews', $this->pages->find("template=reviews, product={$this->page->id}")); } // action accessible via route /reviews/new/ public function reviewsNew() { // Later versions will allow to handle actions depending on REQUEST_TYPE, but for now: if($_SERVER['REQUEST_METHOD'] == 'POST') { // create review logic goes here ... $this->session->redirect(...); } else { $this->set('form', $this->forms->get('review')); } } // action for action route /reviews/:id/vote/ public function reviewsVote() { if($id = $this->input->route->id) { // save vote for review ... } } } Template product’s action templates go into site/templates/views/product/ named index.tmpl.php, reviews.tmpl.php, etc. When we talk about routes in PVC, it means patterns of PW’s urlSegments. If you want to have multiple actions and routes, you have to enable urlSegments for the particular template. Index action is performed when a page is addressed directly via its path. If urlSegments are added to the request, PVC captures the urlSegments as a action route and provides it to the controller which determines the action to perform for the route. Until now all template specific view classes (like ProductsView, ProductView) are generated on the fly. Let’s use some view helpers to reduce logic in templates. For example we want pagination looking all the same all over the site. Therefor we define a general view helper for that in site/templates/views/base.view.php. <?php class BaseView extends PvcView { /** * Add custom view helpers that will be available as * global functions within your templates. * @method customViewHelpers * @param Array $scope contains an associative array of template scope * @returns Array An associative array with key/closure pairs */ public function customViewHelpers($scope) { return array( /** * Each helper is defined as a pair of key (name of the helper * function in template context) and closure (function body) * Via use() you can pass in $scope and custom values to be * available within your helper. * The helper below can be called like this: <?=sayHi('your name');?> */ 'pagination' => function(PageArray $pageArray) use($scope) { return $pageArray->renderPager(array( 'nextItemLabel' => "Next", 'previousItemLabel' => "Prev", 'separatorItemClass' => "pagination__item--separator", 'nextItemClass' => "pagination__item--next", 'previousItemClass' => "pagination__item--prev", 'currentItemClass' => "pagination__item--current", 'lastItemClass' => "pagination__item--last", 'listMarkup' => "<ul class='pagination pagination--{$scope['template']}'>{out}</ul>", 'itemMarkup' => "<li class='pagination__item {class}'>{out}</li>", 'linkMarkup' => "<a href='{url}'><span>{out}</span></a>" )); }) ); } } Now you can render your pagination in your action templates just by passing a PageArray value to your pagination view helper like <?=pagination($reviews);?>. You also can create template-specific view helpers (like gridClass() used in our products action template for index at the top) by creating a view class for the template in site/templates/views/ like this: <?php /* site/templates/views/products.view.php */ class ProductsView extends BaseView { public function customViewHelpers($scope) { $helpers = array( 'gridClass' => function(PageImage $img, $class=null) { $w = $img->width(); $h = $img->height(); $orientation = 'square'; if($w < $h) $orientation = 'portrait'; if($w > $h) $orientation = 'landscape'; return is_string($class) ? sprintf('%s--%s', $class, $orientation) : $orientation; } ); return array_merge($helpers, parent::customViewHelpers($scope)); } } Predefined view helpers are for example embed() to render other pages within your current action template, scripts() and styles() to output asset groups and snippet() to render reusable code chunks stored in site/templates/snippets/ within the current action template’s scope. Hopefully this gives you a vague idea how you can organize your code base using PVC.
    2 points
  12. <nav class="top-bar" data-topbar> <section class="top-bar-section"> <ul class="right"> <li class="divider"></li> <?php $treeMenu = $modules->get("MarkupSimpleNavigation"); // load the module $options = array( 'has_children_class' => 'has-dropdown' ); echo $treeMenu->render($options); // render default menu ?> </li> </ul> </section> </nav> The pattern is very easy. The above example will attach the class "has-dropdown" to every list item that has a submenu. Try to understand the Readme by comparing it to my example and you will understand quickly. Edit: Misspelling corrected
    2 points
  13. --------------------------------------------------------------------------------------------------------------------------------- when working with PW version 2.6+, please use Pim2, not Pim! read more here on how to change from the older to the newer version in existing sites --------------------------------------------------------------------------------------------------------------------------------- PageImage Manipulator, API for version 1 & 2 The Page Image Manipulator is a module that let you in a first place do ImageManipulations with your PageImages. - And in a second place there is the possibility to let it work on any imagefile that exists in your servers filesystem, regardless if it is a 'known PW-image'. The Page Image Manipulator is a Toolbox for Users and Moduledevelopers. It is written to be as close to the Core ImageSizer as possible. Besides the GD-filterfunctions it contains resize, crop, canvas, rotate, flip, sharpen, unsharpMask and 3 watermark methods. How does it work? You can enter the ImageManipulator by calling the method pim2Load(). After that you can chain together how many actions in what ever order you like. If your manipulation is finished, you call pimSave() to write the memory Image into a diskfile. pimSave() returns the PageImage-Object of the new written file so we are able to further use any known PW-image property or method. This way it integrates best into the ProcessWire flow. The three examples above put out the same visual result: a grayscale image with a width of 240px. Only the filenames will slightly differ. You have to define a name-prefix that you pass with the pimLoad() method. If the file with that prefix already exists, all operations are skipped and only the desired PageImage-Object gets returned by pimSave(). If you want to force recreation of the file, you can pass as second param a boolean true: pim2Load('myPrefix', true). You may also want to get rid of all variations at once? Than you can call $pageimage->pim2Load('myPrefix')->removePimVariations()! A complete list of all methods and actions are at the end of this post. You may also visit the post with tips & examples for users and module developers. How to Install Download the module Place the module files in /site/modules/PageImageManipulator/ In your admin, click Modules > Check for new modules Click "install" for PageImageManipulator Done! There are no configuration settings needed, just install and use it. Download (version 0.2.0) get it from the Modules Directory History of origins http://processwire.com/talk/topic/3278-core-imagemanipulation/ ---------------------------------------------------------------------------------------------------------- Page Image Manipulator - Methods * pimLoad or pim2Load, depends on the version you use! pimLoad($prefix, $param2=optional, $param3=optional) param 1: $prefix - (string) = mandatory! param 2: mixed, $forceRecreation or $options param 3: mixed, $forceRecreation or $options return: pim - (class handle) $options - (array) default is empty, see the next method for a list of valid options! $forceRecreation - (bool) default is false It check if the desired image variation exists, if not or if forceRecreation is set to true, it prepares all settings to get ready for image manipulation ------------------------------------------------------------------- * setOptions setOptions(array $options) param: $options - (array) default is empty return: pim - (class handle) Takes an array with any number valid options / properties and set them by replacing the class-defaults and / or the global config defaults optionally set in the site/config.php under imageSizerOptions or imageManipulatorOptions. valid options are: quality = 1 - 100 (integer) upscaling = true | false (boolean) cropping = true | false (boolean) autoRotation =true | false (boolean) sharpening = 'none' | 'soft' | 'medium' | 'strong' (string) bgcolor = (array) css rgb or css rgba, first three values are integer 0-255 and optional 4 value is float 0-1, - default is array(255,255,255,0) thumbnailColorizeCustom = (array) rgb with values for colorize, integer -255 - 255 (this can be used to set a custom color when working together with Thumbnails-Module) outputFormat = 'gif' | 'jpg' | 'png' (Attention: outputFormat cannot be specified as global option in $config->imageManipulatorOptions!) set {singleOption} ($value) For every valid option there is also a single method that you can call, like setQuality(90), setUpscaling(false), etc. ------------------------------------------------------------------- * pimSave pimSave() return: PageImage-Object If a new image is hold in memory, it saves the current content into a diskfile, according to the settings of filename, imagetype, targetFilename and outputFormat. Returns a PageImage-Object! ------------------------------------------------------------------- * release release() return: void (nothing) if you, for what ever reason, first load image into memory but than do not save it, you should call release() to do the dishes! ? If you use pimSave() to leave the ImageManipulator, release() is called automatically. ------------------------------------------------------------------- * getOptions getOptions() return: associative array with all final option values example: ["autoRotation"] bool(true) ["upscaling"] bool(false) ["cropping"] bool(true) ["quality"] int(90) ["sharpening"] string(6) "medium" ["targetFilename"] string(96) "/htdocs/site/assets/files/1124/pim_prefix_filename.jpg" ["outputFormat"] string(3) "jpg" get {singleOption} () For every valid option there is also a single method that you can call, like getQuality(), getUpscaling(), etc. See method setOptions for a list of valid options! ------------------------------------------------------------------- * getImageInfo getImageInfo() return: associative array with useful informations of source imagefile example: ["type"] string(3) "jpg" ["imageType"] int(2) ["mimetype"] string(10) "image/jpeg" ["width"] int(500) ["height"] int(331) ["landscape"] bool(true) ["ratio"] float(1.5105740181269) ["bits"] int(8) ["channels"] int(3) ["colspace"] string(9) "DeviceRGB" ------------------------------------------------------------------- * getPimVariations getPimVariations() return: array of Pageimages Collect all pimVariations of this Pageimage as a Pageimages array of Pageimage objects. All variations created by the core ImageSizer are not included in the collection. ------------------------------------------------------------------- * removePimVariations removePimVariations() return: pim - (class handle) Removes all image variations that was created using the PIM, all variations that are created by the core ImageSizer are left untouched! ------------------------------------------------------------------- * width width($dst_width, $sharpen_mode=null) param: $dst_width - (integer) param: $auto_sharpen - (boolean) default is true was deleted with version 0.0.8, - sorry for breaking compatibility param: $sharpen_mode - (string) possible: 'none' | 'soft' | 'medium' | 'strong', default is 'soft' return: pim - (class handle) Is a call to resize where you prioritize the width, like with pageimage. Additionally, after resizing, an automatic sharpening can be done with one of the three modes. ------------------------------------------------------------------- * height height($dst_height, $sharpen_mode=null) param: $dst_height - (integer) param: $auto_sharpen - (boolean) default is true was deleted with version 0.0.8, - sorry for breaking compatibility param: $sharpen_mode - (string) possible: 'none' | 'soft' | 'medium' | 'strong', default is 'soft' return: pim - (class handle) Is a call to resize where you prioritize the height, like with pageimage. Additionally, after resizing, an automatic sharpening can be done with one of the three modes. ------------------------------------------------------------------- * resize resize($dst_width=0, $dst_height=0, $sharpen_mode=null) param: $dst_width - (integer) default is 0 param: $dst_height - (integer) default is 0 param: $auto_sharpen - (boolean) default is true was deleted with version 0.0.8, - sorry for breaking compatibility param: $sharpen_mode - (string) possible: 'none' | 'soft' | 'medium' | 'strong', default is 'soft' return: pim - (class handle) Is a call to resize where you have to set width and / or height, like with pageimage size(). Additionally, after resizing, an automatic sharpening can be done with one of the three modes. ------------------------------------------------------------------- * stepResize stepResize($dst_width=0, $dst_height=0) param: $dst_width - (integer) default is 0 param: $dst_height - (integer) default is 0 return: pim - (class handle) this performs a resizing but with multiple little steps, each step followed by a soft sharpening. That way you can get better result of sharpened images. ------------------------------------------------------------------- * sharpen sharpen($mode='soft') param: $mode - (string) possible values 'none' | 'soft'| 'medium'| 'strong' return: pim - (class handle) Applys sharpening to the current memory image. You can call it with one of the three predefined pattern, or you can pass an array with your own pattern. ------------------------------------------------------------------- * unsharpMask unsharpMask($amount, $radius, $threshold) param: $amount - (integer) 0 - 500, default is 100 param: $radius - (float) 0.1 - 50, default is 0.5 param: $threshold - (integer) 0 - 255, default is 3 return: pim - (class handle) Applys sharpening to the current memory image like the equal named filter in photoshop. Credit for the used unsharp mask algorithm goes to Torstein Hønsi who has created the function back in 2003. ------------------------------------------------------------------- * smooth smooth($level=127) param: $level - (integer) 1 - 255, default is 127 return: pim - (class handle) Smooth is the opposite of sharpen. You can define how strong it should be applied, 1 is low and 255 is strong. ------------------------------------------------------------------- * blur blur() return: pim - (class handle) Blur is like smooth, but cannot called with a value. It seems to be similar like a result of smooth with a value greater than 200. ------------------------------------------------------------------- * crop crop($pos_x, $pos_y, $width, $height) param: $pos_x - (integer) start position left param: $pos_y - (integer) start position top param: $width - (integer) horizontal length of desired image part param: $height - (integer) vertical length of desired image part return: pim - (class handle) This method cut out a part of the memory image. ------------------------------------------------------------------- * canvas canvas($width, $height, $bgcolor, $position, $padding) param: $width = mixed, associative array with options or integer, - mandatory! param: $height = integer, - mandatory if $width is integer! param: $bgcolor = array with rgb or rgba, - default is array(255, 255, 255, 0) param: $position = one out of north, northwest, center, etc, - default is center param: $padding = integer as percent of canvas length, - default is 0 return: pim - (class handle) This method creates a canvas according to the given width and height and position the memory image onto it. You can pass an associative options array as the first and only param. With it you have to set width and height and optionally any other valid param. Or you have to set at least width and height as integers. Hint: If you want use transparency with rgba and your sourceImage isn't of type PNG, you have to define 'png' as outputFormat with your initially options array or, for example, like this: $image->pimLoad('prefix')->setOutputFormat('png')->canvas(300, 300, array(210,233,238,0.5), 'c', 5)->pimSave() ------------------------------------------------------------------- * flip flip($vertical=false) param: $vertical - (boolean) default is false return: pim - (class handle) This flips the image horizontal by default. (mirroring) If the boolean param is set to true, it flips the image vertical instead. ------------------------------------------------------------------- * rotate rotate($degree, $backgroundColor=127) param: $degree - (integer) valid is -360 0 360 param: $backgroundColor - (integer) valid is 0 - 255, default is 127 return: pim - (class handle) This rotates the image. Positive values for degree rotates clockwise, negative values counter clockwise. If you use other values than 90, 180, 270, the additional space gets filled with the defined background color. ------------------------------------------------------------------- * brightness brightness($level) param: $level - (integer) -255 0 255 return: pim - (class handle) You can adjust brightness by defining a value between -255 and +255. Zero lets it unchanged, negative values results in darker images and positive values in lighter images. ------------------------------------------------------------------- * contrast contrast($level) param: $level - (integer) -255 0 255 return: pim - (class handle) You can adjust contrast by defining a value between -255 and +255. Zero lets it unchanged, negative values results in lesser contrast and positive values in higher contrast. ------------------------------------------------------------------- * grayscale grayscale() return: pim - (class handle) Turns an image into grayscale. Remove all colors. ------------------------------------------------------------------- * sepia sepia() return: pim - (class handle) Turns the memory image into a colorized grayscale image with a predefined rgb-color that is known as "sepia". ------------------------------------------------------------------- * colorize colorize($anyColor) param: $anyColor - (array) like css rgb or css rgba - but with values for rgb -255 - +255, - value for alpha is float 0 - 1, 0 = transparent 1 = opaque return: pim - (class handle) Here you can adjust each of the RGB colors and optionally the alpha channel. Zero lets the channel unchanged whereas negative values results in lesser / darker parts of that channel and higher values in stronger saturisation of that channel. ------------------------------------------------------------------- * negate negate() return: pim - (class handle) Turns an image into a "negative". ------------------------------------------------------------------- * pixelate pixelate($blockSize=3) param: $blockSize - (integer) 1 - ??, default is 3 return: pim - (class handle) This apply the well known PixelLook to the memory image. It is stronger with higher values for blockSize. ------------------------------------------------------------------- * emboss emboss() return: pim - (class handle) This apply the emboss effect to the memory image. ------------------------------------------------------------------- * edgedetect edgedetect() return: pim - (class handle) This apply the edge-detect effect to the memory image. ------------------------------------------------------------------- * getMemoryImage getMemoryImage() return: memoryimage - (GD-Resource) If you want apply something that isn't available with that class, you simply can check out the current memory image and apply your image - voodoo - stuff ------------------------------------------------------------------- * setMemoryImage setMemoryImage($memoryImage) param: $memoryImage - (GD-Resource) return: pim - (class handle) If you are ready with your own image stuff, you can check in the memory image for further use with the class. ------------------------------------------------------------------- * watermarkLogo watermarkLogo($pngAlphaImage, $position='center', $padding=2) param: $pngAlphaImage - mixed [systemfilepath or PageImageObject] to/from a PNG with transparency param: $position - (string) is one out of: N, E, S, W, C, NE, SE, SW, NW, - or: north, east, south, west, center, northeast, southeast, southwest, northwest default is 'center' param: $padding - (integer) 0 - 25, default is 5, padding to the borders in percent of the images length! return: pim - (class handle) You can pass a transparent image with its filename or as a PageImage to the method. If the watermark is bigger than the destination-image, it gets shrinked to fit into the targetimage. If it is a small watermark image you can define the position of it: NW - N - NE | | | W - C - E | | | SW - S - SE The easiest and best way I have discovered to apply a big transparency watermark to an image is as follows: create a square transparent png image of e.g. 2000 x 2000 px, place your mark into the center with enough (percent) of space to the borders. You can see an example here! The $pngAlphaImage get centered and shrinked to fit into the memory image. No hassle with what width and / or height should I use?, how many space for the borders?, etc. ------------------------------------------------------------------- * watermarkLogoTiled watermarkLogoTiled($pngAlphaImage) param: $pngAlphaImage - mixed [systemfilepath or PageImageObject] to/from a PNG with transparency return: pim - (class handle) Here you have to pass a tile png with transparency (e.g. something between 150-300 px?) to your bigger images. It got repeated all over the memory image starting at the top left corner. ------------------------------------------------------------------- * watermarkText watermarkText($text, $size=10, $position='center', $padding=2, $opacity=50, $trueTypeFont=null) param: $text - (string) the text that you want to display on the image param: $size - (integer) 1 - 100, unit = points, good value seems to be around 10 to 15 param: $position - (string) is one out of: N, E, S, W, C, NE, SE, SW, NW, - or: north, east, south, west, center, northeast, southeast, southwest, northwest default is 'center' param: $padding - (integer) 0 - 25, default is 2, padding to the borders in percent of the images length! param: $opacity- (integer) 1 - 100, default is 50 param: $trueTypeFont - (string) systemfilepath to a TrueTypeFont, default is freesansbold.ttf (is GPL & comes with the module) return: pim - (class handle) Here you can display (dynamic) text with transparency over the memory image. You have to define your text, and optionally size, position, padding, opacity for it. And if you don't like the default font, freesansbold, you have to point to a TrueTypeFont-File of your choice. Please have a look to example output: http://processwire.com/talk/topic/4264-release-page-image-manipulator/page-2#entry41989 ------------------------------------------------------------------- PageImage Manipulator - Example Output
    1 point
  14. Introducing PVC PvcCore: https://github.com/oliverwehn/PvcCore/ PvcRendererTwig: https://github.com/oliverwehn/PvcRendererTwig/ (coming soon) PvcGenerator: https://github.com/oliverwehn/PvcGenerator/ (coming soon) Each time I’ve built a ProcessWire page I’ve struggled with organizing (and separating) code, markup and stuff. Playing around with frameworks (backend as well as frontend) like Rails, Ember and stuff I really liked having a given structure, knowing where to put what piece of code. Therefor I started working on a MVCish way to deal with templates in PW that considers the $page object kind of the data/model layer and adds View and Controller upon it. First by just catching everything via a small processor file added to all PW templates as altFilename. I’ve digged a bit deeper since then and hooked into the native rendering process, have been refactoring my code base more than a dozen times. Now I got a first version that seem to work and I’d love some of you guys to try it out! PVC (instead of MVC) stands for Page-View-Controller, as it considers PW’s $page var the model/data layer. I’m still working on the README.md on GitHub to document the basics. So have a look for more detailed infos there. I’ll give you a short overview here: Code separation: PVC introduces views and controllers to your PW templates as well as multiple action templates. Controllers, as most of you already know, keep all the business logic. Controllers execute actions wired to routes (urlSegment patterns). Even routes with dynamic segements (e.g. /edit/:id/) can be defined and assigned to an action, providing input through $this->input->route. Values can be set on the controller to be accessable in your templates later on. It’s also possible to set dynamic values as closures to be calculated (e.g. using field values of the current page) on render. Also controllers allow you to set layouts, styles and scripts to be available in your layout or template. Logic can be shared through inheritance between controllers. Views introduce view helpers. Helpers are functions that are made available to you (only) within your template context. There are predefined ones like embed(), snippet(), styles() or scripts(). But you can implement your own helpers easily and share them among your view classes through inheritance. Action templates contain the actual markup. Every action defined in a controller uses its own template. So the same page can display content accordingly to the action that was addressed via urlSegments/route. Within templates you can access all field values and values set on your controller like globals (e.g. <?=$title?>). Modular renderers: PVC implements rendering through separate renderer modules. PvcCore comes with PvcRendererNative that gives you template syntax the good ol’ PW/PHP way. A Twig renderer is in the making. And maybe you want to build your own renderer for the template syntax of your choice? I consider the module an early Beta version. So make sure to try it within a save environment! Would love to get some feedback (and error reports). I’m no professional developer, so code quality may suck here and there. So I’m glad for inputs on that, too. Also there is some old stuff in there yet, I still have to get rid of.
    1 point
  15. Ok, that -is suffix is also new to me, at least that it is implemented now. I remember we (Ryan, Nico, me) have had a talk 6 month ago that it would be good if image variations belonging to RTEs get flagged somehow. Without a flag there is / was a great chance that they get deleted with a call for $image->removeVariations(). Whereas all API created image variations in templates get recreated on demand after such a call, RTE-belonging images don't get recreated and the pages output was / is broken. Therefore it is a good implementation to flag them. @mike131: I think you should add the same code to your emulation: $image = $event->object->getPageimage(); $width = (int) $this->input->get->width; $height = (int) $this->input->get->height; $options = array(); if ($width < $image->width) { // add a suffix if it is a resized version, don't add a suffix if it is the original unresized image $options["suffix"] = array("is"); } $resizedImage = $image->size($width, $height, $options); $filename = $resizedImage->filename; ...
    1 point
  16. Maybe this helps someone. Nerd alert! Currently building a shop module for a project, where I was looking for a easy way to handle/store form data in session and later repopulate it easily using form API. It can be very tedious to do that manually grab the fields, store in session repopulate form. So I found a way to do it "automatically" by serializing form object and build a name => value array that I store in session, then retrieve the array later and convert it to WireInputData as it is required for form object to process. Further I needed to turn of CSRF temporarely to get around error when populating the form object. Here a example code for those interested. // generate $form // when sent if($input->post->send) { // process form $form->processInput($input->post); // if no errors if(!count($form->getErrors())){ // serialize form values and store in "shop" session namespace $formfields = $form->getAll(); $formdataKeys = $formfields->explode(function($item, $key){ return $item->name; }); $formdataValues = $formfields->explode(function($item, $key){ return $item->value; }); $formdata = array_combine($formdataKeys, $formdataValues); $session->setFor("shop", "userformdata", $formdata ); $session->redirect("nextpageurl"); } } else { // if session formdata found repopulate form object if($formdata = $session->getFor("shop", "userformdata")){ $formdataInput = new WireInputData($formdata); $form->protectCSRF = false; // to not get a CSRF validation error $form->processInput($formdataInput); // fills in form and validates it $form->protectCSRF = true; } } return $form->render();
    1 point
  17. Let's see what happens. Of course alternatively, serializing the form object also works quite simply with a foreach, without using PW's WireArray::explode() which is fun anyway. After all the trick here is the $form->getAll(), which returns a InputfieldWrapper containing a flat array of only the fields whithout fieldsets and nested wrappers. And example of how to populate the form directly without using processInput($data), which requires to toggle the CSRF and the form validates and show errors when rendering the form. So setting values to the form object using $form->get(field)->attr("value", $value) does that "silently" and it doesn't trigger any validation thus not show errors when initially loading the form. if($input->post->send) { $form->processInput($input->post); if(!count($form->getErrors())){ $exclude = array("send"); // skip fields by name foreach($form->getAll() as $field) { if(in_array($field->name, $exclude)) continue; $formdata[$field->name] = strip_tags($field->value); } $session->setFor("shop", "userformdata", $formdata ); $session->redirect($this->page->url . $this->nextStepSegment); } } else { // populate data to form inputfields without using processInput(), which processes the form if($formdata = $session->getFor("shop", "userformdata")){ foreach($formdata as $name => $value) $form->get($name)->attr("value", $value); } } return $form->render();
    1 point
  18. I think Phillip inadvertantly forgot the actual save part Try this: public function saveShortUrl($event) { $page = $event->arguments[0]; //#todo Rename to your field names. $page->domain = parse_url($page->source_url,PHP_URL_HOST); //#todo Maybe some more error handling. $page->of(false); $page->save("domain"); $this->message("Save the domain {$page->domain}."); } As Phillip mentions - you need to have a field called "domain", or rename both instances of "domain" in the code above. Hope that helps.
    1 point
  19. Smells like a ProcessWire Recipe Or make a module out of it?
    1 point
  20. For security. I wanted to add, that the stored values in the array are not entity encoded and if you don't strip tags they're stored as entered, so you'd have to take care of that and entity encode with htmlspecialchars() them before printing them somewhere or use a sanitizer. When using the form render() it already takes care of that when populating the inputfields. It's still possible you have or want to allow tags, so it's a question of what you do with the data. Always be careful and if in doubt ask a experienced developer. foreach($formdata as $name => $val){ ... $out .= "<td>" . htmlspecialchars($val, ENT_QUOTES, "UTF-8") . "</td>"; ... } You could add a strip tags when getting the values like this: $formdataValues = $formfields->explode(function($item, $key){ return strip_tags($item->value); });
    1 point
  21. Great minds "almost" think alike: https://processwire.com/talk/topic/7274-are-there-better-fields-naming-convention/?p=70106 Similar suggestion, but for adding fields to templates.
    1 point
  22. http://assessment.ifas.ufl.edu I've been working on this one a good while now. What's there now is essentially a phase one MVP (Minimum Viable Product). We start the next phase of the project soon, which migrates a lot more data, and takes all the paper processes and turns them into web forms and/or calculation tools. More on that another time. For those of you familiar with the pitfalls of infinite scroll — I'm still working out the kinks with history.js, but I wanted to go ahead and post the site here as it's now officially live. Some of the more crucial modules used: ListerPro AIOM ProFields: PageTable FormBuilder (not live yet, coming in phase 2) Homepage Search Page Filters Species Page
    1 point
  23. All the taxonomy is handled by page fields. Some are just basic fields like Origin and Growth habit, and others like Conclusion Type and Zones are part of a PageTable. (Screenshots at the end of the post). There is a lot of JS involved in the filters — more than I have time to explain at the moment. The short version: Filter selections build a URL containing the page IDs for any selected filters via JS. We needed the URIs to be as short as possible, since they will be frequently emailed, and eventually cited in publications. They end up looking something like: /?zones=1030,1028&types=1082,1080&growth_habit=19040,1022 A selector is then built from those GET variables in the template. // default selector, used for assessment page $selector = "template=species, limit=16, sort=name,"; // zones GET variables if ($input->get->zones){ $zones = explode(",", $input->get->zones); $q = implode("|", $zones); $selector .= "@conclusions.conclusion_zones={$q}, check_access=0,"; } It gets a little more complicated, because of the infinite scroll. A maximum of 16 results are initially shown for any query, additional items are pulled in via AJAX on scroll. So if there are GET variables involved, the AJAX call needs to pass them along. In the JS function getUrlVars() { var vars = {}; var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; }); return vars; } var GET_zones = getUrlVars()["zones"]; There is a GET_* for each possible filter. All of which are passed via the data param in the $.ajax() call. data: { start:start, query:query, zones:GET_zones, types:GET_types, origin:GET_origin, growth_habit:GET_growth_habit, tool_used:GET_tool_used }, Screenshots This is a bit of a disjointed explanation, but should give you some idea.
    1 point
  24. I think there was a discussion about this some time ago in a thread here. While I quite like the ideas, I see some challenges that comes with this approach Who is handling the payment? What about taxes? How to "book" this income? How exactly should they work? Flattr? Paypal Donate? Why not just leave it up to the Developer, to include a Donate Link in his/her description? And I'm not sure if that many people would donate after all. If we/Ryan spent about 20-30 hours building the donate function and we only collect 200-300 Dollards in Donation after all..... - better build another great module
    1 point
  25. Further reading (sorry, German only): http://www.peterkropff.de/site/php/arrays.htm
    1 point
  26. <little offtopic> Actually the best bet is to buy 299$/€/£ laptop, 199$/€/£ Android and iPhone and look all the sites through those. I think that will represent the masses (not the designers with their high end monitors of course). </little offtopic>
    1 point
  27. And, as you were mentioning it, there is no such thing like "accurate colours" in webdesign. Your best bet is to purchase a monitor with neutral colour balance, sharpness and good viewing angle. The overall quality matters. And that's it. If you would like to make print work that's a different beast. Than accuracy matters a lot.
    1 point
  28. Hi mikeroosa and welcome to PW. Both of those are optional. The leading underscore is simply a convention so you know those files are not actual template files, but rather php includes (files that get included into other files). This is also common outside of PW. The omission of the closing tag has several benefits. A quick google will help to explain why: https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=php+omit+closing+tag
    1 point
  29. I wonder if the Add Field dialog on the templates page could be enhanced to use the field's tags as optgroup dividers in the select field. I can see that might be useful if you have a lot of fields.
    1 point
  30. PageImage Manipulator - Tips & Examples * how to create a PNG with transparency for the watermarkLogo method If you can use adobe photoshop, you simply may download and install this action: photoshop_action_PW-png-creations.zip create an empty image (transparent, not white or black) of 2000 x 2000 pixel write / paste your text and / or logo in a single color, (e.g. black) when finished with your text you should have one single layer with text on transparent background then click the action PW-png-creations -> 2000px-square-to-smooth and you are done. Hhm, maybe before saving you want to tweak the global transparency of the image a bit. That one used in the ProcessWire example was set to 75% instead of 100%. Just try out what looks best for you. ------------------------------------------------------------------- * did you know that you can save to different file formats, regardless of source format? You only have to specify your desired format (gif, jpg, png) with the optionally options array with a key named outputFormat and pass it with your call to pimLoad() or use setOptions() before any other action-method: // assuming the first image is a jpeg $img = $page->images->first(); // define outputFormat $options = array('outputFormat'=>'png'); // apply it together with other actions $myPng = $img->pimLoad('myPrefix')->setOptions($options)->width(240)->pimSave(); //------------------------------------------------------------------------------------------ // you may also do it as a OneLiner only with the image format conversion $myPng = $page->images->eq(0)->pimLoad('myPrefix', array('outputFormat'=>'png'))->pimSave(); // or you can use the setOutputFormat method $myPng = $page->images->first()->pimLoad('myPrefix')->setOutputFormat('png')->pimSave(); ------------------------------------------------------------------- * (how) can I use the ImageManipulator with other imagefiles than PW-Pageimages? You can load any imagefile from your servers filesystem into the ImageManipulator with: $pim = wire('modules')->get('PageImageManipulator')->imLoad($imageFilename); // or $pim = $wire->modules->get('PageImageManipulator')->imLoad($imageFilename, $options); You can directly with the imLoad-method pass specific $options or you can do a separate call to setOptions(). Then you do your desired actions and last but not least you call save()! Most time I think the original passed file gets overwritten with the manipulation result, but you are also able to save to a different name and / or fileformat. If so, it is useful to get the final (sanitized) filename back after saveing. $optionalNewFilename = $pim->setOptions($options)->height(360)->flip()->blur()->save(); Also you may call this in one line if you prefer: if(false!==$wire->modules->get('PageImageManipulator')->imLoad($imageFilename,$options)->height(360)->flip()->blur()->save()) { // success !! } ------------------------------------------------------------------- * how can I use the PageImageManipulator with my own module/s? If you build a module that do some image manipulation you can define the PIM as needed dependency in your ModulesInfo method with the key 'requires'. You may also force to install the PIM if it isn't already with the key 'installs': public static function getModuleInfo() { return array( // ... 'requires' => array('PageImageManipulator'), 'installs' => 'PageImageManipulator', // ... ); } detailed infos are here: http://processwire.com/talk/topic/778-module-dependencies/ additionally, if you need to check if a module dependency has a minimum version number, you can do it in your install method like this: public function ___install() { // check that at least the minimum version number is installed $needed = '0.0.3'; $a = wire('modules')->get('PageImageManipulator')->getModuleInfo(); $actual = preg_replace('/(\d)(?=\d)/', '$1.', str_pad("{$a['version']}", 3, "0", STR_PAD_LEFT)); if(version_compare($actual, $needed, '<')) { throw new WireException(sprintf($this->_(__CLASS__ . " requires PageImageManipulator %s or newer. Please update."), $needed)); return; } // ... more code } ------------------------------------------------------------------- * global options in site/config.php You can create a config-array in your site/config.php. If you look into it you will find a config array for the ImageSizer that comes with the PW core $config->imageSizerOptions = array( 'autoRotation' => true, 'sharpening' => 'soft', 'upscaling' => true, 'cropping' => true, 'quality' => 90 ); You can define another array with these keys: $config->imageManipulatorOptions = array( 'autoRotation' => true, 'sharpening' => 'soft', 'upscaling' => false, 'cropping' => true, 'quality' => 90, 'bgcolor' => array(255,255,255,0), ); You don't have to specify all of the options. PiM reads the imageSizerOptions and merge them with the imageManipulatorOptions. So if you want to have different values you can specify them in imageManipulatorOptions to override those from imageSizerOptions. Only one option isn't present with the imageSizer: bgcolor. This is only used by the imageManipulator. ------------------------------------------------------------------- * using PiM together with the awesome Thumbnails Module (http://mods.pw/1b) If you use the Thumbnails Module together with PiM, you can set two options in the site/config.php under imageManipulatorOptions: $config->imageManipulatorOptions = array( // ... 'thumbnailColorizeCustom' => array(40,-35,0), 'thumbnailCoordsPermanent' => true ); For the colorize dropdown select you can define the custom color here and with the second param you enable/disable permanent storage of RectangleCoords and params. The coords and params are stored with Thumbnails Module per session, but are lost after the session is closed. If you enable permanent storage these data is written into a custom IPTC field of the original imagefile. ------------------------------------------------------------------- * some more examples will folow here . . . -------------------------------------------------------------------
    1 point
  31. hey i'll add to the rant @totoff - you mean themeforest i think ? i think the prefabs are necessary for some devs and users, and for certain projects; I'm a sworn PW user, but i have a site running joomla because there is a really good invoicing system called nBill; and some CMS have advanced prebuilt addons (a.k.a. plugins/modules/components etc..) like community, calendars etc.; so you have to do research and consider budgets before you choose the cms for the project. When you can use PW you'll be relieved, it has the best admin UI hands down of any CMS. i just got done converting a wordpress template, one that I liked a lot, to use in a processwire site – it was really educational; i was able to see how the wp theme was coded and it wasn't a pretty site. Tons of code bloat (but all necessary to make the theme usable to a wide audience); and then i was able to go and attain all of the functionality of the wordpress version and more using 1/20th of the code; and i'm able to do really cool things now with the content management, media (audio, video) that would be completely impossible in WP, or would be a ridiculous hack job...
    1 point
  32. hi, same here: my profession is designer and copwriter, not coder. i still have difficulties to think like "real" coders but i'm progressing. however, here is what i found after having discovered pw for me (i came from contao via textpattern to pw and i have some good knowledge of wp too): coding is fun coding with pw is even more fun because it rewards you with success pw gives me the superpower i always wanted when i tried to adapt contao's pre-made markup to my needs you would like to do the same with wp you can do with pw? good luck - go and learn advanced php. beginner skills will not be enough apart from this, i'm not sure if making wp themes is a good business. if i look at themegarden for example it seems quite competitive. why not specialize in custom tailored websites to clients that appreciate it? from my experience, this market is competitive too, but working. enjoy pw!
    1 point
×
×
  • Create New...