Leaderboard
Popular Content
Showing content with the highest reputation on 09/17/2015 in all areas
-
Edit: The title of this post has been renamed to use the word "processor" instead of "builder" - this is not a form-building module. I'm currently putting together a simple developer-centric form processor for one of my projects, and have decided that I'd like to release it as a module as soon as it's stable enough. The idea is to separate it from the backend, and use per-form configuration files and templates instead. I could well implement a backend solution for this, but my preference is for it to be developer-centric. For me, this makes it easier to use and, of course, develop. Here's how it currently works: developer specifies forms and their particulars in a JSON file stored in the module's directory. The file includes dictations such as the name of the form, the fields it uses (along with their sanitization/validation rules), template information, and a set of emails to send when the form is being processed. An example of such configuration is: { "contact": { "name": "Contact Form", "fields": { "name": { "sanitize": "text", "rules": { "required": "Please enter your name." } }, "email": { "sanitize": "email", "rules": { "required": "We need to know your email address so we can get back to you.", "email": "That doesn't look like a valid email address." } }, "company": { "sanitize": "text", "rules": { "min(4)": "That's a tad short for a company name." } }, "contact": { "sanitize": "text", "rules": { "int": "Please enter only the digits of your phone number (no spaces or other punctuation)." } }, "message": { "sanitize": "entities1|textarea", "textField": true, "rules": { "required": "Please enter your enquiry/message.", "min(250)": "Please enter at least {$0} (but no more than 2000) characters.", "max(2000)": "You have reached the {$0} character limit. Please shorten your message." } } }, "info": { "fromName": "The ABC Accounting Team", "tel": "(011) 100 1234", "altTel": "(011) 100 5678" }, "emails": { "autoReply": { "template": "auto-reply", "to": "{input.name} <{input.email}>", "from": "ABC Accounting <noreply@abc.accounting>", "subject": "Enquiry/Message Submitted - Thanks!" } } } } As seen in the 'emails' key, templates can be defined for each email. These templates can be plain/HTML/both, and accept information regarding form input, the 'info' key, and a custom stylesheet, which is created as a file, but imported directly into the HTML version of the template. The module will also come with a jQuery module to assist in processing the form. Frontend is up to the developer/designer. Currently, the directory structure of the module is: root - forms.config.json / templates / form-name - template-name.html - template-name.css - template-name.txt I'm now thinking that it would be better to change the structure to this: root / form-name / templates - template-name.html - template-name.css - template-name.txt - config.json That is: each form will have its own folder containing configuration and templates. So I'm starting this thread to ask the following: Firstly, what do you think of this idea, and do you think you would make use of this module? Of the two structures above, which one would you prefer? Would you want the ability to make use of attachments in your emails (such as a logo)? (If I'm not mistaken, we'd then need to require WireMailSmtp or WireMailSwiftMailer...) As a side note, it's worth mentioning that this module is really intended to be used on small- to medium-sized sites that require multiple forms where developers are not in a position to obtain Ryan's excellent FormBuilder. Any input here is most welcome. (And yes, as gathered by my signature, the module is called SimpleForms. If you have a name suggestion, please feel free...)9 points
-
Welcome to the forums Tom! All kudos to Soma for the cheatsheet. Best thing since sliced bread More detailed examples are a little slower in happening but some of the items do have examples, not all. Shift and Pop are like their PHP array equivalents - shift gets the first item from the array, pop the last, and essentially removes it from the array for use right now. So your example would be something like: // Shift the first item off the beginning of the array to use right now. It's no longer in the array for this instance of the page $featured = $page->gallery->shift(); echo $featured->size(800,550)->url; // Get the footer item now for use later on - we don't want to iterate over it when displaying the other images just below: $footer = $page->gallery->pop(); // Now do some funky gallery stuff - this instance of the gallery array no longer contains the first and last items it did earlier foreach ($page->gallery as $item) { echo $item->size(400,400)->url; } // And now we can echo the footer echo $footer->size(800,550)->url; That should work, though typed into the browser and untested - let us know how you get on P.S. It is also perfectly acceptable to create two new single-image fields for featured and footer - might keep things neater in the admin for you - but this was an interesting request to explain some less-used functionality I think so I went with it6 points
-
Plyr Media Player for ProcessWire ! beta status. This module is "work in progress" v0.2 ! Please be patient as this is my very first public module ^^ This module adds the Plyr HTML5 Media Player (plyr.io) to ProcessWire. Plyr is basically a wrapper for the natural media interface in modern browsers. It adds the ability for easy styling via CSS and a sprite, while being fully responsive. Also Plyr gives you full controll over the player with its great javascript interface. MarkupPlyrMediaPlayer incorporates Plyr for ProcessWire. -> GitHub -> Module directory Current capabilities After installation, you will notice some module configuration options. These are: - Automatic Mode If enabled, this option will automaticaly add all needed resources into your pages output. - Use CDN Use the official Plyr CDN (Content Delivery Network) for resources? The following resource options are only required if you don't wish to use the CDN: - Path to CSS file (Path to your CSS file, required to style the players.) - Path to Plyr library (Path to the Plyr javascript library, required for the functionality.) - Path to SVG sprite (Path to your SVG sprite image file, required to style the players.) Automatic mode If automatic mode is enabled, the module hooks after the page rendering and automatically adds the stylesheet to HTML head. Also adds an AJAX call to fetch the SVG sprite and the Plyr javascript library right before the ending body-tag. Also, while in automatic mode, that extra markup will only be rendered if a template made a render request for a Plyr player. So there will be no unnecessary load on your site. Get module $plyr = $modules->get("MarkupPlyrMediaPlayer"); Add a video player to your template echo $plyr->renderVideoPlayer($poster, $mp4, $webm, $captions); The $captions-Array contains details of the caption tracks: $captions = $caption = array(); $caption['label'] # Something like "English captions" $caption['src'] # http://...movie_captions_en.vtt $caption['srclang'] # en|de|ru|... $caption['default'] # true|false array_push($captions, $caption); Add an audio player to your template echo $plyr->renderAudioPlayer($mp3Path, $oggPath); Add the YouTube-wrapper to your template echo $plyr->renderYoutubePlayer($videoId); Manual mode If automatic mode is disabled, you have to render these parts manualy in your page template. Important: This method will not check if a player was requested. In the HTML head: <html> <head> ... <?php echo $plyr->renderHeadLink(); // Basicly just a <link rel="stylesheet" href="..."> ?> </head> ... And in the footer somewhere before the closing body-tag: ... echo $plyr->renderScripts; // AJAX call for SVG and JS library inclusion </body> </html> Where is this going? Before getting a v1.0.0 stable release, this module should be capable of following features: - [done] Load resources from CDN or local files - Reliable automatic mode with fallback to local - Brings specific Inputfields for video, audio and youtube for the backend and frontend markup rendering - Every Plyr javascript setting can be handled via module configuration4 points
-
you mean counting like this? $kids = $pages->find("template=poi, has_parent=$page"); $interests = new PageArray(); foreach ($kids as $k) $interests->import($k->interests); $iTotal = count($interests); foreach ($interests as $i) $i->useCount = count($pages->find("interests=$i")); echo "<h3>Interests ($iTotal)</h3>"; echo '<ul>'; foreach ($interests->sort("-useCount") as $i) { echo "<li><a href='interest/$i->name'>$i->title</a> ($i->useCount)</li>"; } echo '</ul>';3 points
-
I'm working on a few big updates atm on multiple PW sites. For me, every day is a ProcessWire day.3 points
-
Hi, In wire/config.php, you can see: /*** 1. SYSTEM MODES ****************************************************************************/ /** * Enable debug mode? * * Debug mode causes additional info to appear for use during site development and debugging. * This is almost always recommended for sites in development. However, you should * always have this disabled for live/production sites since it reveals more information * than is advisible for security. * * #notes This enables debug mode for ALL requests. See the debugIf option for an alternative. * * @var bool * */ $config->debug = false; /** * Enable debug mode if condition is met * * Set debug mode to be false above, and then specify any one of the following here: * 1) IP address of user required to enable debug mode; * 2) Your own callable function name (i.e. "debug_mode") in /site/config.php that returns * true or false for debug mode; * 3) PCRE regular expression to match IP address of user (must start and end with a "/" * slash). If IP address matches, then debug mode is enabled. Regular expression * example: /^123\.456\.789\./ would match all IP addresses that started with 123.456.789. * * #notes When used, this overrides $config->debug, changing it at runtime automatically. * @var string * */ $config->debugIf = ''; /** * Tools, and their order, to show in debug mode (admin) * * Options include: pages, api, session, modules, hooks, database, db, timers, user, input, cache * * @var array * */ $config->debugTools = array( 'pages', 'api', 'session', 'modules', 'hooks', 'database', // PDO 'db', // mysqli 'timers', 'user', 'input', 'cache', ); /** * Enable ProcessWire advanced development mode? * * Turns on additional options in ProcessWire Admin that aren't applicable in all instances. * Be careful with this as some options configured in advanced mode cannot be removed once * set (at least not without going directly into the database). * * #notes Recommended mode is false, except occasionally during ProcessWire core or module development. * @var bool * */ $config->advanced = false; /** * Enable demo mode? * * If true, disables save functions in Process modules (admin). * */ $config->demo = false; Putting $config->debug = true; in site/config.php enables debug mode. You also have Admin > Setup > Logs > Logs are in site/assets/logs/ (and perhaps elsewhere(?)).2 points
-
you have some options... <?php // version using PageArray(); $kids = $pages->find("template=poi, has_parent=$page"); $interests = new PageArray(); foreach ($kids as $k) $interests->import($k->interests); echo '<ul>'; foreach ($interests as $i) { echo "<li><a href='interest/$i->name'>$i->title</a></li>"; } echo '</ul>'; // or find all interests, cycle through but ignore those that don't apply to this page $interests = $pages->find("template=interest"); echo '<ul>'; foreach ($interests as $i) { if(!count($pages->find("template=poi, has_parent=$page, interests=$i"))) continue; echo "<li><a href='interest/$i->name'>$i->title</a></li>"; } echo '</ul>'; ?> wow, 3 replies!2 points
-
Image Animated GIF v 2.0.2 Module for PW 2.5 stable or newer, but is obsolete for PW Versions greater then 3.0.89 (... read more ...) This module helps with resizing and cropping of animated GIFs when using the GD-Library. The GD-Library does not support this. This module is completely based upon the fantastic work of László Zsidi (http://www.gifs.hu/, builts the initial classes) xurei (https://github.com/xurei/GIFDecoder_optimized, enhanced the classes) I have ported it to a PW module and it works with core imagefields, together with Pia and with CropImagefields that uses the new naming scheme since PW 2.5. ------------------------------------------------------------------------------------------------------------------------------------------ read more in this post about the rewrite from version 1.0.0 to version 2.0.0 ------------------------------------------------------------------------------------------------------------------------------------------ You can find it in the modules directory: https://modules.processwire.com/modules/image-animated-gif/ and on Github: https://github.com/horst-n/ImageAnimatedGif ------ A preview can be found here1 point
-
Like others here, I build sites that require reuse of images. In my case, the images must always be accompanied by correct credits and descriptions, and must be replaced sitewide when our contract with the photographer ends. So centralized image storage is a must, and one page per image works fine. The challenge is selecting image pages from other pages in an easy, visual way. Soma's images module is a great move in that direction, but for my needs, users should work only with thumbs, never with HTML. The default pages field seems like it's allllmost there. I'd just like one of the field label choices to be the image field, and to choose a page by thumbnail. Ideally, the thumb will be shown on the page after selection, as it is with the images field. Even more ideally, the page picker will include search. Even even more ideally, I'd have the time and php chops to build this module myself.1 point
-
I didn't know this one Shortest way to echo a variable only if populated (using pw fields of course ): echo $page->field?:''; and: echo $page->field ?: "field is empty"; // echoes field content echo $page->empty_field ?: "field is empty"; // echoes "field is empty" or even: echo $page->field1 ?: $page->field2 ?: "they are all empty";1 point
-
1 point
-
making a page select field display as thumbnails should not be too hard to do: http://rvera.github.io/image-picker/ but that's only good for few images. if you have lots of pages to select it would get trickier and even trickier with an autocomplete field... not much help from my side, i know good luck1 point
-
Filetype is JPEG you said? If you change things for testing purposes, you can add a param "forceNew" => true to an options array to always override previous versions. And if you want check filesize compared to quality settings you can use the suffix setting for a complete check loop like that: $img = $page->images->first(); // grab you an image (change code to match your setup) $newWidth = ($img->width == 2500) ? 2499 : 2500; // set a width value different than the original image size! (is needed for the test only) $qualities = array(100, 90, 80, 70, 60, 50, 40, 30, 20, 10); foreach($qualities as $q) { $options = array('forceNew'=>true, 'quality'=>$q, 'upscaling'=>true, 'sharpening'=>'soft', 'suffix'=>"quality{$q}"); $variation = $img->width($newWidth, $options); echo "<p>variation: {$variation->name} :: " . filesize($variation->filename) . "</p>"; } Code is written in browser, if it doesn't work as expected, please check for typos or come back here and tell me. And if it works, please drop a note about the result.1 point
-
Sorry guys, that was environmental problem, may be with image library. I did not find out true reason, but on my laptop the problem is not reproducable: crop works correctly.1 point
-
Hi folks! I'm currently using the Pages::__save() hook within a custom module to inform an external service that a page was saved. Now I only need to inform the external service if a valid page was saved (no field validation errors occurred). ProcessWire saves the page (even published pages) regardless of any field validation errors (e.g. missing input for a required field). Is their any way of validating a page instance within my module? Something like $myPage->isValid()? It would also help if someone could point me to the relevant lines of source code where the ProcessWire editor validates page input on saving. Regards, Marco1 point
-
Incidentally, @Macrura, your first suggestion is also now working. No idea why it failed yesterday, but the PageArray version is humming along smoothly now. (Each "interest" is, indeed, a unique page stored under an Interests page.) I will definitely use the PageArray version since it will allow me superior sorting options (er, once I figure out how to fiddle with arrays and do the counting part; as I said: PHP noob). Thanks again.1 point
-
@Tomas: I didn't know what you already knew or had done, so I posted it in case it helped you or anyone else in the future.1 point
-
In order to properly help you, please let us know a little more about your environment (Versions of ProcessWire, PHP and MySQL), to include information about your repeater field and any other changes (fields, modules, configuration) that are unique to your installation. Thanks.1 point
-
It says 0 because you didn't specify a height. When using ->size(500, 300) it will be xxx.500x300.jpg. For the sizing issue I cannot help further, there are people more experienced in the topic than me.1 point
-
That is so much cleaner than I expected it to be! I guess I misunderstood shift() and pop() and it works so much better than I thought it did originally! Ah ProcessWire just keeps getting better and better! Thank you very much!1 point
-
If it is a Pagearray you could test before output HTML string with $pageArray->has($page); reference: https://processwire.com/talk/topic/2433-check-if-pagearray-already-contains-a-page/ regards mr-fan1 point
-
You could filter them out in a temporary array...e.g. //example code $interests = $pages->find('template=poi, interests!=""'); //method 1 foreach ($interests as $int) { foreach ($int->interests as $p) {//interests is a multi page field; PW returns them as objects $array1[$p->id] = $p->title;//overwrite duplicate ids in the array key } } //method 2 foreach ($interests as $int) { foreach ($int->interests as $p) { if(in_array($p->id, $array2)) continue;//if we already have that id, skip it $array2[] = $p->id; } } //testing echo '<pre>'; print_r($array1); echo '</pre>'; echo count($array1); echo '<hr>'; echo '<pre>'; print_r($array2); echo '</pre>'; echo count($array2); Above are just examples. You could even store objects in the arrays, or create a temporary WireArray and store them in there. WireArray and PageArray docs: http://processwire.com/api/arrays/ Btw, the above code will not do the counting you want. That's easily doable as well... Edit: Reading your question again, this is probably not what you want...Oh well, code stays though..1 point
-
Hey Tom, Thanks. I've been using a similar looking theme I built locally for a long time, and I forget sometimes that it doesn't ship with the Reno Theme. What I will probably do is release the theme I have in a manner similar to the way @nico did with his LightWire theme. Actually, I may just see if Nico would release an additional color scheme for LightWire — no sense duplicating effort.1 point
-
Update to Version 1.1.3 (dev) Download from github https://github.com/kixe/FieldtypeSelectExtOption/tree/dev Changes hook in Inputfield render() replaced by adding magic toString() method to SelectExtOption class (which helped teppo and dsdb) @Teppo Thanks! filter() method is now hookable to define more complex SQL WHERE clauses. whole usage description available in module settings. from now all column values are populated as a property if the column is not named by a reserved word. Reserved words are: 'value','label','row' and 'data'. $page->myfield->value $page->myfield->label $page->myfield->row // associative array of all values of the selected datatablerow $page->myfield->columnname-1 $page->myfield->columnname-2 // ... I tested the Module with PW 2.6.17. Please give me feedback if the module works in your surroundings.1 point
-
Maybe this helps you. I'm using it in one of our sites for the exact same thing (you'll have to adjust the table names and get the coordinates of the given zip, though). The SQL Query uses the Haversine formula ( http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/ ) to find coordinates within the given radius. /** * Retrieves a list of address records residing within the given $radius of the given geo location * * @param float $lat * @param float $lng * @param int $radius * @return array */ private function proximitySearch($lat, $lng, $radius = 20) { $sql = <<<SQL SELECT * FROM ( SELECT *, ( ( 2 * 6378.2 ) * ATAN2( ( SQRT( POW( SIN( ( ( $lat * PI() / 180 ) - ( lat * PI() / 180 ) ) / 2 ), 2 ) + COS( lat * PI() / 180 ) * COS( $lat * PI() / 180 ) * POW( SIN( ( ( $lng - lng ) * PI() / 180 ) / 2 ), 2 ) ) ), ( SQRT( 1 - ( POW( SIN( ( ( $lat * PI() / 180 ) - ( lat * PI() / 180 ) ) / 2 ), 2 ) + COS( lat * PI() / 180 ) * COS( $lat * PI() / 180 ) * POW( SIN( ( ( $lng - lng ) * PI() / 180 ) / 2 ), 2 ) ) ) ) ) ) AS distance FROM field_address_team ORDER BY distance ) AS distributordistance WHERE distance <= $radius; SQL; $result = wire('db')->query($sql); if(!function_exists('mysqli_fetch_all')) { $retVal = []; while ($row = $result->fetch_assoc()) { $retVal[] = $row; } } else { $retVal = $result->fetch_all(MYSQLI_ASSOC); } return $retVal; } Usage (in this specific example the radius is extended by the factor 3 until at least 3 locations are found or the radius has been extended 3 times which would be 540km [(((20*3)*3)*3)] with default radius settings ): public function getTeamsInRadius() { $teamsArr = new \PageArray(); $searchCount = 0; while (count($teamsArr) < 3 && $searchCount <= 3 ) { try { // extend search radius by factor 3 as long as result set counts less than 3 hits // $teams = $this->proximitySearch($this->latitude, $this->longitude, $this->radius * pow(3, $searchCount)); foreach( $teams as $team ) { $teamsArr->append( wire('pages')->get($team['pages_id']) ); } $searchCount++; } catch (\Exception $e) { break; } } return $teamsArr; } A good idea when using this is to cache the results (see this blog entry for examples) for each entered ZIP until new entries are added to the database as the SQL Queries are pretty performance intensive. The benefit of this method is: You don't have to query Google Maps (or another GeoService) every time you're searching for locations.1 point
-
thanks for the hint. There are 2 new files to translate in 2.6.17. Translation updates are now available (https://github.com/Manfred62/pw-lang-de-dev). The "Edit" must first be added in the wire/templates-admin/default.php to get translated. In my translation file it's already included. See GitHub: https://github.com/ryancramerdesign/ProcessWire/issues/13971 point
-
Hi Sevarf2 Pw's solution with the extended paths uses another directory structure, so you need to migrate the files somehow. Here's a link to a gist from my migration script: https://gist.github.com/wanze/e8051e0bf754c2f75083 Basically I'm doing the following stuff: Rename "site/assets/files" to "site/assets/files_old" Create a new "site/assets/files" folder Loop the pages and copy all their files from old location to new location (using pageFileExtended) That's it. If anything goes wrong, all files are still available in the old directory. Cheers1 point
-
I like the idea. I have been looking for proper way to version control PW sites recently, and have not ended with a clear decision for myself. Of course "it depends on a project". But we can come up with a tutorial helping make the choices. What to version in git I never tried initialising a git repo in templates folder, as Ryan suggested here. Custom modules and now site/ready.php should go to version control, as well as config.php. For me the choiсe is either to version the whole installation or only the /site folder. As I usually modify the .htaccess I am leaning to the former. The next thing is what to ignore. Some think you should ignore /wire, some think it is worth having it in the repo. If we could (I mean If I knew how to) install the needed version of PW core as a dependency via composer or include it in a similar way automatically after deployment / git checkout, it would be better to leave /wire off. But for simplicity it could be better not to exclude it as it is quite small. That definately should be excluded is some part of site/assets. If the site is a big one, excluding site/assets/files is a must. But for a small near to static it is probably worthless. You should probably ignore these almost every time not to mess with constantly changing data: site/assets/cache site/assets/sessions site/assets/logs I found no reason not to include all modules to the VCS. Deployment Speaking about deployment, I do not like the idea to deploy every time I commit (which seems to be the case if using git-hooks, if I am getting it right). There are other ways for deployment with git, but I an intrigued by doing it with something like this or this (both are capistrano-like deployment tools in php). Anyway, I do not seem to find a way to easily deploy database changes. Maybe in the case of semi-static sites it is possible to dump a database and restore in with git-hooks (or to include a sql dump from sites/assets/backup/database to the revision and manually restore it), but it probably will never work with subscription sites and rich-content sites managed by clients. The only way to keep track of changes made to the database via PW GUI (admin) I came up with is keeping a journal. I made a folder where I include subfolders related to git commits with JSON export files for fields, templates and forms, which should be imported. Pages are just described in .txt as I know of no way to export them to something like JSON. It would be awesome to have something like the things discussed here available not to do it manually. Hope it is somehow useful. I would be delighted to hear how others do it, as I am certainly only an amateur in all this stuff.1 point
-
I'd think this really depends on the project. Also it's nothing that is really specific to ProcessWire, so I don't think this should be part of the docs.1 point
-
Was just reminded of this module as I stumbled upon the Wild Beasts x Mattis Dovier GIF-novel. Also read an interview where the artist (at least I think it was him..) declared that GIF is making a come-back, or something. Can't really disagree after seeing the GIF-novel1 point
-
It depends on what kind of field your "color" is. If it is a textarea, integer or other "basic", then you can check it like this: color=0 If it is page field, then this will do the job: color.count=0 EDIT: Leaving it empty just like Pete and Some suggested works too,1 point