Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/25/2018 in all areas

  1. Page Query Boss Build complex nested queries containing multiple fields and pages and return an array or JSON. This is useful to fetch data for SPA and PWA. You can use the Module to transform a ProcessWire Page or PageArray – even RepeaterMatrixPageArrays – into an array or JSON. Queries can be nested and contain closures as callback functions. Some field-types are transformed automatically, like Pageimages or MapMarker. Installation Via ProcessWire Backend It is recommended to install the Module via the ProcessWire admin "Modules" > "Site" > "Add New" > "Add Module from Directory" using the PageQueryBoss class name. Manually Download the files from Github or the ProcessWire repository: https://modules.processwire.com/modules/page-query-builder/ Copy all of the files for this module into /site/modules/PageQueryBoss/ Go to “Modules > Refresh” in your admin, and then click “install” for the this module. Module Methods There are two main methods: Return query as JSON $page->pageQueryJson($query); Return query as Array $page->pageQueryArray($query); Building the query The query can contain key and value pairs, or only keys. It can be nested and contain closures for dynamic values. To illustrate a short example: // simple query: $query = [ 'height', 'floors', ]; $pages->find('template=skyscraper')->pageQueryJson($query); Queries can be nested, contain page names, template names or contain functions and ProcessWire selectors: // simple query: $query = [ 'height', 'floors', 'images', // < some fileds contain default sub-queries to return data 'files' => [ // but you can also overrdide these defaults: 'filename' 'ext', 'url', ], // Assuming there are child pages with the architec template, or a // field name with a page relation to architects 'architect' => [ // sub-query 'name', 'email' ], // queries can contain closure functions that return dynamic content 'querytime' => function($parent){ return "Query for $parent->title was built ".time(); } ]; $pages->find('template=skyscraper')->pageQueryJson($query); Keys: A single fieldname; height or floors or architects The Module can handle the following fields: Strings, Dates, Integer… any default one-dimensional value Page references Pageimages Pagefiles PageArray MapMarker FieldtypeFunctional A template name; skyscraper or city Name of a child page (page.child.name=pagename); my-page-name A ProcessWire selector; template=building, floors>=25 A new name for the returned index passed by a # delimiter: // the field skyscraper will be renamed to "building": $query = ["skyscraper`#building`"] Key value pars: Any of the keys above (1-5) with an new nested sub-query array: $query = [ 'skyscraper' => [ 'height', 'floors' ], 'architect' => [ 'title', 'email' ], ] A named key and a closure function to process and return a query. The closure gets the parent object as argument: $query = [ 'architecs' => function($parent) { $architects = $parent->find('template=architect'); return $architects->arrayQuery(['name', 'email']); // or return $architects->explode('name, email'); } ] Real life example: $query = [ 'title', 'subtitle', // naming the key invitation 'template=Invitation, limit=1#invitation' => [ 'title', 'subtitle', 'body', ], // returns global speakers and local ones... 'speakers' => function($page){ $speakers = $page->speaker_relation; $speakers = $speakers->prepend(wire('pages')->find('template=Speaker, global=1, sort=-id')); // build a query of the speakers with return $speakers->arrayQuery([ 'title#name', // rename title field to name 'subtitle#ministry', // rename subtitle field to ministry 'links' => [ 'linklabel#label', // rename linklabel field to minlabelistry 'link' ], ]); }, 'Program' => [ // Child Pages with template=Program 'title', 'summary', 'start' => function($parent){ // calculate the startdate from timetables return $parent->children->first->date; }, 'end' => function($parent){ // calculate the endate from timetables return $parent->children->last->date; }, 'Timetable' => [ 'date', // date 'timetable#entry'=> [ 'time#start', // time 'time_until#end', // time 'subtitle#description', // entry title ], ], ], // ProcessWire selector, selecting children > name result "location" 'template=Location, limit=1#location' => [ 'title#city', // summary title field to city 'body', 'country', 'venue', 'summary#address', // rename summary field to address 'link#tickets', // rename ticket link 'map', // Mapmarker field, automatically transformed 'images', 'infos#categories' => [ // repeater matrix! > rename to categories 'title#name', // rename title field to name 'entries' => [ // nested repeater matrix! 'title', 'body' ] ], ], ]; if ($input->urlSegment1 === 'json') { header('Content-type: application/json'); echo $page->pageQueryJson($query); exit(); } Module default settings The modules settings are public. They can be directly modified, for example: $modules->get('PageQueryBoss')->debug = true; $modules->get('PageQueryBoss')->defaults = []; // reset all defaults Default queries for fields: Some field-types or templates come with default selectors, like Pageimages etc. These are the default queries: // Access and modify default queries: $modules->get('PageQueryBoss')->defaults['queries'] … public $defaults = [ 'queries' => [ 'Pageimages' => [ 'basename', 'url', 'httpUrl', 'description', 'ext', 'focus', ], 'Pagefiles' => [ 'basename', 'url', 'httpUrl', 'description', 'ext', 'filesize', 'filesizeStr', 'hash', ], 'MapMarker' => [ 'lat', 'lng', 'zoom', 'address', ], 'User' => [ 'name', 'email', ], ], ]; These defaults will only be used if there is no nested sub-query for the respective type. If you query a field with complex data and do not provide a sub-query, it will be transformed accordingly: $page->pageQueryArry(['images']); // returns something like this 'images' => [ 'basename', 'url', 'httpUrl', 'description', 'ext', 'focus'=> [ 'top', 'left', 'zoom', 'default', 'str', ] ]; You can always provide your own sub-query, so the defaults will not be used: $page->pageQueryArry([ 'images' => [ 'filename', 'description' ], ]); Overriding default queries: You can also override the defaults, for example $modules->get('PageQueryBoss')->defaults['queries']['Pageimages'] = [ 'basename', 'url', 'description', ]; Index of nested elements The index for nested elements can be adjusted. This is also done with defaults. There are 3 possibilities: Nested by name (default) Nested by ID Nested by numerical index Named index (default): This is the default setting. If you have a field that contains sub-items, the name will be the key in the results: // example $pagesByName = [ 'page-1-name' => [ 'title' => "Page one title", 'name' => 'page-1-name', ], 'page-2-name' => [ 'title' => "Page two title", 'name' => 'page-2-name', ] ] ID based index: If an object is listed in $defaults['index-id'] the id will be the key in the results. Currently, no items are listed as defaults for id-based index: // Set pages to get ID based index: $modules->get('PageQueryBoss')->defaults['index-id']['Page']; // Example return array: $pagesById = [ 123 => [ 'title' => "Page one title", 'name' => 123, ], 124 => [ 'title' => "Page two title", 'name' => 124, ] ] Number based index By default, a couple of fields are transformed automatically to contain numbered indexes: // objects or template names that should use numerical indexes for children instead of names $defaults['index-n'] => [ 'Pageimage', 'Pagefile', 'RepeaterMatrixPage', ]; // example $images = [ 0 => [ 'filename' => "image1.jpg", ], 1 => [ 'filename' => "image2.jpg", ] ] Tipp: When you remove the key 'Pageimage' from $defaults['index-n'], the index will again be name-based. Help-fill closures & tipps: These are few helpfill closure functions you might want to use or could help as a starting point for your own (let me know if you have your own): Get an overview of languages: $query = ['languages' => function($page){ $ar = []; $l=0; foreach (wire('languages') as $language) { // build the json url with segment 1 $ar[$l]['url']= $page->localHttpUrl($language).wire('input')->urlSegment1; $ar[$l]['name'] = $language->name == 'default' ? 'en' : $language->name; $ar[$l]['title'] = $language->getLanguageValue($language, 'title'); $ar[$l]['active'] = $language->id == wire('user')->language->id; $l++; } return $ar; }]; Get county info from ContinentsAndCountries Module Using the [ContinentsAndCountries Module](https://modules.processwire.com/modules/continents-and-countries/) you can extract iso code and names for countries: $query = ['country' => function($page){ $c = wire('modules')->get('ContinentsAndCountries')->findBy('countries', array('name', 'iso', 'code'),['code' =>$page->country]); return count($c) ? (array) $c[count($c)-1] : null; }]; Custom strings from a RepeaterTable for interface Using a RepeaterMatrix you can create template string for your frontend. This is usefull for buttons, labels etc. The following code uses a repeater with the name `strings` has a `key` and a `body` field, the returned array contains the `key` field as, you guess, keys and the `body` field as values: // build custom translations $query = ['strings' => function($page){ return array_column($page->get('strings')->each(['key', 'body']), 'body', 'key'); }]; Multilanguage with default language fallback Using the following setup you can handle multilanguage and return your default language if the requested language does not exist. The url is composed like so: `page/path/{language}/{content-type}` for example: `api/icf/zurich/conference/2019/de/json` // get contenttype and language (or default language if not exists) $lang = wire('languages')->get($input->urlSegment1); if(!$lang instanceof Nullpage){ $user->language = $lang; } else { $lang = $user->language; } // contenttype segment 2 or 1 if language not present $contenttype = $input->urlSegment2 ? $input->urlSegment2 : $input->urlSegment1; if ($contenttype === 'json') { header('Content-type: application/json'); echo $page->pageQueryJson($query); exit(); } Debug The module respects wire('config')->debug. It integrates with TracyDebug. You can override it like so: // turns on debug output no mather what: $modules->get('PageQueryBoss')->debug = true; Todos Make defaults configurable via Backend. How could that be done in style with the default queries? Module in alpha Stage: Subject to change This module is in alpha stage … Query behaviour (especially selecting child-templates, renaming, naming etc) could change
    9 points
  2. I've added the new sticky pagelist action, @theo's langswitcher fix, Tracy panel z-index fix (hopefully) and other minor fixes in v1.9.1. I noticed that I was using one SCSS mixin too many times (for icon-only pagelist actions) and it contained rules that I could apply to items outside the mixin. After cleaning this up the final CSS shrinked from 127 to 93 Kb so it was worth the trouble. I removed the js lib "perfect scrollbar" that was used to replace the browser scrollbar with a mini one (RenoTweaks). From now on AOS uses CSS to achieve the same thing, and is available in Chrome only (you can find it under Misc). It's a sacrifice but results in much leaner code, is controlled by the browser so it's unlikely to break, and modifies every scrollbar in the admin. For example they are available in Tracy panels too and also in CKEditors (the latter required additional efforts though): Documentation is in progress, as usual
    4 points
  3. @bernhard just liked the original post after a few days passed, and I got notified. So decided to put a little update here. There are actually some web-design related thing I learned from this situation: Do not rely on cdn's for jquery, fonts and stuff. Opera actually is not that useless browser, as it has Turbo Mode. Thanks for support!
    4 points
  4. Hi @BitPoet, if you've got a spare moment do you mind sharing what you've done? I am quite intrigued. (Perhaps in a separate thread and not hijack this one) When you say it's really fast, I assume you don't mean XDebug but some other methodology/tools for debugging.
    2 points
  5. This one also is very cool: https://codyhouse.co/
    2 points
  6. Try: $datetofind=strtotime($date); foreach($page->special_days->find("date_value={$datetofind}, time_from!='', time_to!=''") as $special_day) { $slot_txt.=$special_day->time_from." to ".$special_day->time_to."<br/>"; }
    2 points
  7. xdebug has always been slow (all over Google). Some things you can do Disable xdebug Profiler Disable xdebug Profiler enable trigger Disable xdebug auto trace Disable xdebug auto start (if you can) Helpful hints http://www.devinzuczek.com/anything-at-all/i-have-xdebug-and-php-is-slow/
    2 points
  8. Introducing our newest [commercial] module: Recurme Processwire Recurring Dates Field & Custom Calendar Module. http://www.99lime.com/modules/recurme/ One Field to Recur them ALL… A Recurring Dates InputField for your Processwire templates. The InputField you’ve been waiting for. Complex RRule date repeating in a simple and fast user interface. Use the super simple, & powerful API to output them into your templates. example: <? // easy to get recurring events $events = $recurme->find(); // events for this day $events = $recurme->day(); // events for this week $events = $recurme->week(); // events for this month $events = $recurme->month(); ?> <? // Loop through your events foreach($events as $event){ echo $event->title; echo $event->start_date; echo $event->rrule; echo $event->original->url; ... } ?> Unlimited Custom Calendars. Imagine you could create any calendar you wanted on your website. Use recurring events with the Recurme field, or use your own Processwire pages and date fields to render calendars… it’s up to you. Fully customizable. Make as many calendars as you like. Get events from anywhere. Recurme does all the hard date work for you. Unlimited Custom Admin Calendars too. Hope you like it , Joshua & Eduardo from 99Lime. ## [1.0.1] - 2017-05-29 ### changed - Fixed $options[weekStartDay] offset in Calendar - Fixed ->renderCalendar() Blank Days - Fixed missing ->renderList() [renderMonth][xAfter] - Removed ->renderCalendar() <table> attributes border, border-spacing - Fixed ->renderCalendar() excluded dates - Fixed rrule-giu.js exclude dates - Fixed ->renderList missing space in attr ID (shout out to @Juergen for multiple suggestions & feedback).
    1 point
  9. Non-exhaustive list of css ressources that we may need for some projects (if not mistaken, I haven't used any of them for the moment, except the Mozilla one): https://jonathantneal.github.io/sanitize.css/ https://github.com/jonathantneal/postcss-normalize http://browserl.ist/ https://github.com/browserslist/browserslist https://css-tricks.com/browserlist-good-idea/ https://evilmartians.com/chronicles/autoprefixer-7-browserslist-2-released https://leaverou.github.io/prefixfree/ https://github.com/ismay/stylelint-no-unsupported-browser-features https://github.com/anandthakker/doiuse https://stylelint.io/ https://github.com/ntwb/awesome-stylelint http://cssnano.co/ https://www.10bestdesign.com/dirtymarkup/ https://www.styled-components.com/ ( https://marksheet.io/ ) [ https://developer.mozilla.org/en-US/ ]
    1 point
  10. Hi, based on the work of @microcipcip and @gebeer (see their posts here and here), I put together a Processwire + React boilerplate (profile). Github repo: https://github.com/lapico/process-react Cheers, K
    1 point
  11. Please see the current version of this module here: https://modules.processwire.com/modules/rock-finder/
    1 point
  12. Thanks for the remainder @Robin S. I've replaced the character icon with an SVG. I've committed the changes, no version bump. Perhaps I would have used FontAwesome if it would have been possible to set it as a background-image but that's not the case. I've tried adding the SVG variant of the FA search icon but then searched for a slimmer one. There are only a few icons in AOS and I wouldn't like to increase the overall module size.
    1 point
  13. Wow, da hätt glaubs öpper gschaffed... trotz de Früehligs-Polle From just a very quick first glance, this looks really nice. I'm sure I'll install this when I have some spare time and play around with it. I don't actually have a real use-case myself atm, but since we're experimenting with conversational interface stuff lately (chatbots etc.), Dialogflow Webhooks etc., this could come in very handy for REST/API-like scenarios.
    1 point
  14. Thats what I built it for
    1 point
  15. @noelboss, this is BEAUTIFUL!! Very easy to understand. I'm eager to play with it and create a front-end using Vuejs and another with Gatsbyjs. Many thanks for this module!!
    1 point
  16. Thanks for the thread @Soma. One of the most important and cited ones in the whole forum history! In the original post there are a few points that seem to be not discussed later in the thread, but which are extremely interesting to me. 1. Are there any good examples of those to dig into? Gists maybe? 2. Looking here it seems arrays are not allowed. I might be not understanding it right or things might change since when it was written. Is there actually a way to process input from a page or an array? 3. There was already a question about what kind of validation processInput does and @adrian's answer too. I read the code a few times but still not sure should I sanitize values after processInput before saving to page fields or not. Is it necessary? Thanks again! Learning ProcessWire is still fun (or am I doing it too slow?!)
    1 point
  17. Hello, friends! These days it is not that easy to join you here on the forums if you happen to be anywhere in Russia. You probably heard about our government's struggle to ban Telegram. And ProcessWire's ip is in the list. At these moments you start to understand just how important can a seemingly remote online community be in your everyday life and work. Thank you all for being here. As long as VPN's still function we can stay together .
    1 point
  18. Who will use these data entries? What will happen with all these data entries? How many data entries will there be each minute/hour/day/week? How long will they be stored? Will they be archived/deleted? Will someone create charts from it? Will they be exported to another programm/system? Will there be JSON/XML/RSS exports/strems/feeds or even an API? Will ProcessWire provide those access details for each dongle/user/door? There are so many best ways to go depending these paramters and variables.
    1 point
  19. Hi all - I have started a new 3.0 branch which has some more breaking changes. This new version moves the country code into it's own "data_country" database field and stores a raw version of the number in the default "data" field. The reason for this is to make it possible to do a: $pages->find("phone=13727654876") Before you could only find by component parts, like: $pages->find("phone.country=1, phone.are_code=372, phone.number=7654876") My need for this was to find a user by their full raw/unformatted phone number as returned by the Twilio sms service's POST response. I'll keep the changes in this branch for a while, but I would encourage new installs to try this version. Let me know how it goes.
    1 point
  20. @adrian, until a fix is found a workaround is to set one (or both) of the Page Reference fields to dereference as a PageArray. Related issue: https://github.com/processwire/processwire-issues/issues/152
    1 point
  21. Hi @harmvandeven, OK. Makes sense. It doesn't sound too difficult given the Vimeo/YT API. I'm thinking we'll add a setting in MM for users to indicate whether they'll want to view/manage online content such as YouTube. We'll create a list for this but currently, support only YT and Vimeo. Later, we could expand this to include other media sources. We can add the input to the upload screen as a third tab (only visible if users indicate they'll want to view/manager online content such as Vimeo). So, Add / Scan / Online (or Other or something appropriate) - I'll be removing the 'Help' tab. With good documentation, we don't need it. I'll be working on the docs once version 012 is in beta testing. We'll also have an input for the media Title. We'll either reuse the file field that video media use to store the image or copy and reuse the image field that image media use in the video media templates. We'll use an InputfieldTextarea field to store the embed code and other data. We can just reuse the Textarea field we use for MM settings - copy that to the video template. Again, this field will only be added to the video template if online content feature will be used. For the frontend, we'll have video media return a property with the data required for video output. I think that should cover it. OK. I'll have a look.
    1 point
  22. In your example @JoelB95, just use pw-before ... <div pw-before="page-content"> <h1><?= 'BEFORE #page-content' ?></h1> </div> <div id="page-content"> <h1><?=$page->title?></h1> Overview page </div> <div pw-after="page-content"> <h1><?= 'AFTER #page-content' ?></h1> </div>
    1 point
  23. I'm surprised this hasn't come up yet: https://tympanus.net/codrops/
    1 point
  24. Recently discovered: Layout Land by Jen Simmons on YouTube. https://www.youtube.com/channel/UC7TizprGknbDalbHplROtag
    1 point
  25. @Zeka you need to go to Gmail settings and allow access for less secure apps there. Then it should work.
    1 point
  26. I'll give this a try, thanks. Thanks, had a problem submitting, 2mins+ with nothing haopening so I refreshed, waited, waited, redreshed, tried again. Third time submitted normally i.e. took seconds. Not sure what went wrong, maybe dodgy internet.
    1 point
  27. I made it work with PHP 5.x just by changing one line. SubscribeToMailchimp.module - Line 23 - before: public function subscribe(string $email, array $data = [], string $list = "") { SubscribeToMailchimp.module - Line 23 - after: public function subscribe( $email, $data = [], $list = "") { This works without any problems so far.
    1 point
  28. Thanks for sharing Daniels! It would be a good idea to make it backwards compatible with PHP 5.5 so that it works on older installations otherwise mention that it has PHP 7 dependency. Regards!
    1 point
  29. server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; root /home/forge/example.com/public; index index.html index.htm index.php; charset utf-8; # ----------------------------------------------------------------------------------------------- # Access Restrictions: Protect ProcessWire system files # ----------------------------------------------------------------------------------------------- # Block access to ProcessWire system files location ~ \.(inc|info|module|sh|sql)$ { deny all; } # Block access to any file or directory that begins with a period location ~ /\. { deny all; } # Block access to protected assets directories location ~ ^/(site|site-[^/]+)/assets/(cache|logs|backups|sessions|config|install|tmp)($|/.*$) { deny all; } # Block acceess to the /site/install/ directory location ~ ^/(site|site-[^/]+)/install($|/.*$) { deny all; } # Block dirs in /site/assets/ dirs that start with a hyphen location ~ ^/(site|site-[^/]+)/assets.*/-.+/.* { deny all; } # Block access to /wire/config.php, /site/config.php, /site/config-dev.php, and /wire/index.config.php location ~ ^/(wire|site|site-[^/]+)/(config|index\.config|config-dev)\.php$ { deny all; } # Block access to any PHP-based files in /templates-admin/ location ~ ^/(wire|site|site-[^/]+)/templates-admin($|/|/.*\.(php|html?|tpl|inc))$ { deny all; } # Block access to any PHP or markup files in /site/templates/ location ~ ^/(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ { deny all; } # Block access to any PHP files in /site/assets/ location ~ ^/(site|site-[^/]+)/assets($|/|/.*\.php)$ { deny all; } # Block access to any PHP files in core or core module directories location ~ ^/wire/(core|modules)/.*\.(php|inc|tpl|module)$ { deny all; } # Block access to any PHP files in /site/modules/ location ~ ^/(site|site-[^/]+)/modules/.*\.(php|inc|tpl|module)$ { deny all; } # Block access to any software identifying txt files location ~ ^/(COPYRIGHT|INSTALL|README|htaccess)\.(txt|md)$ { deny all; } # Block all http access to the default/uninstalled site-default directory location ~ ^/site-default/ { deny all; } #Amplify dashboard location /nginx_status { stub_status on; allow 127.0.0.1; deny all; } # ----------------------------------------------------------------------------------------------- # If the request is for a static file, then set expires header and disable logging. # Give control to ProcessWire if the requested file or directory is non-existing. # ----------------------------------------------------------------------------------------------- location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|eot|woff|ttf)$ { expires 15d; log_not_found off; access_log off; try_files $uri $uri/ /index.php?it=$uri&$query_string; } # ----------------------------------------------------------------------------------------------- # ProCache Rules # ----------------------------------------------------------------------------------------------- set $cache_uri $request_uri; if ($request_method = POST) { set $cache_uri 'nocache'; } if ($http_cookie ~* "wires_challenge") { set $cache_uri 'nocache'; } if ($http_cookie ~* "persist") { set $cache_uri 'nocache'; } # ----------------------------------------------------------------------------------------------- # This location processes all other requests. If the request is for a file or directory that # physically exists on the server, then load the file. Else give control to ProcessWire. # ----------------------------------------------------------------------------------------------- location / { expires -1; try_files /site/assets/ProCache-b3d534d...d/$cache_uri/index.html $uri $uri/ /index.php?it=$uri&$args; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/example.com-error.log error; error_page 404 /index.php; location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; fastcgi_index index.php; include fastcgi_params; } location ~ /\.ht { deny all; } }
    1 point
  30. "Government guys" all over the world just do not understand that there is no such thing as "only officials can exploit security measures on behalf of the law". If they force backdoors to be implemented into software/hardware then anyone with enough technical skills can also walk through that door. They do not understand the basics of IT security, they live in their dream worlds trying to make the internet less secure therefore introducing more chaos instead of order they say they are striving for. They are doing quite the opposite what they are saying. Why am I not surprised?
    1 point
  31. I've recently switched to IIS for development. Still a little bit of manual work (once you know what you're doing, you're up-and-running in less than an hour, though) but once it's up, it's really fast.
    1 point
  32. Xdebug is not really known for being a performant analysis tool and processwire does sometimes generate quite deeply nested function stacks, which xdebug will fully log. Also wamp isn't really the environment for super performant php anyway.
    1 point
×
×
  • Create New...