Jump to content

Leaderboard

Popular Content

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

  1. If you have any modules that check for ProcessWire version and don't use PHP version_compare, but instead use a string comparison, the comparison will fail. The modules that I know of that use this are in the Selectize group of inputfields and are being updated to a new version that fixes this. UPDATE 1: All of my modules that used the bad version comparison will be updated by tomorrow. UPDATE 2: All of the Selectize modules are now updated to work with PW 3.0.100 (fixed version comparison)
    3 points
  2. 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
    2 points
  3. You only use autoload if the module needs to load automatically when ProcessWire boots so that you can listen to every single request and typically attach hooks to some event of interest. Don't let this confuse you though. Modules can hook into events without being autoload modules. An example autoload module is Blog module's Publish Date. It listens to when Blog Posts are published and sets a publish date. As such, it needs to be auto-loaded. Does your module need to boot with ProcessWire or does one call it when one needs it? If the latter, then it means presently, it is just loading and using up resources when it doesn't need to. Can your module work like this? $pageQuery = $modules->get('PageQueryBoss'); $query = $pages->find('template=skyscraper'); $json = $pageQuery->pageQueryJson($query); It doesn't seem to me like it needs to autoload, but I've only had a brief look, so I could be wrong. You can read a bit more about autoload modules in the module class docs here.
    2 points
  4. CKEditor 5 v10.0.0 – the future of rich text editing looks stable .
    2 points
  5. Hi, and welcome, You can get any image from any page with the $pages variable. Basic use is like this: $image = $pages->get('/path/to/page/')->imagefield-> Examples: $mypage = $pages->get('/path/to/mypage/'); $myimage = $mypage->images->get("name=myimage.jpg"); You can also use shorthand rules or hanna code to write more compact code More here: https://processwire.com/api/variables/pages/
    2 points
  6. Depends on your use case, but.. that's not entirely true. When you embed an image into a CKEditor field, for an example, you get to choose from which page you want to pick the image from. Similarly you can request an image from any given page via the API in your template files. So no, an image is not strictly tied to one page: you can embed images anywhere, and you can indeed use them in multiple places on your site. There are also some modules that make reusing media easier, such as MediaLibrary (free) and Media Manager (commercial). It is true, though, that behind the scenes an image is always connected to a single page, and because of that ... A) you can't have a single image showing up in image fields of multiple pages, B) only one copy of each image file is stored in a page-specific directory under /site/assets/files/, and C) if you have restricted access to a given page and enabled $config->pagefileSecure, access to files (including images) on that page will also be restricted.
    2 points
  7. Hi, If you are looking for the grid only part of Bootstrap, there is no need anymore to compile this for your self. I noticed that Bootstrap has already split up the files in the download package. In the dist folder you can find the following files: bootstrap-grid.css = 37 kb bootstrap-grid.min.css = 29 kb And here is the css to give a bootstrap container any width you want: .container{ max-width: 1300px; /* use any width for your container without less or sass */ width:100%; }
    1 point
  8. @Jan235, I think not. But there is a 7 day "Satisfaction guarantee" period with full refund. See here.
    1 point
  9. @cstevensjr thanks for the reply. I found that links before, but read to fast..., now understand that is still in development/testing phase. Before 2 years I build JSON fieldtype (for configuration only), but sometimes, I use it to store contact details. Because never totally finished, I didn't post it to module section. Please, allow me to suggest that in case of this new fieldtypes (FieldsetGroup and FieldsetPage), to try to find another one option for multilanguage tabs to reduce space in user interface (and to get some kind of "compact view"). To be more clear, here are some screenshots of my JSON configuration filedtype. Compact view/layout: Field settings: Thanks for Ryan and others who are involved in development of this new fieldtypes. Best regards. EDIT: here is that module and you can try it
    1 point
  10. I was able to reproduce this issue. It seems to occur when any of the pages being cloned have file or image fields in their template. If the parent page has a file/image field but not the children then setting output formatting off before cloning the page seems to work. But if the child pages have a file/image field then setting output formatting off on those children doesn't work. But I don't think output formatting should need to be off when cloning a page - the clone() docs make no mention of output formatting and don't show it being set in the example code, and indeed it doesn't need to be off unless a file/image field is present. And seeing as setting output formatting off in the child pages still doesn't allow for a successful clone I'd say this is a bug. @simonsays, do you want to open an issue for this in the GitHub issues repo?
    1 point
  11. No surprise here.. I guess I am from the old school. A 'long time' ago, logos used to be background images set on anchors (<a> tags). Menu items (<a> tags) used to have background images called sprites that would 'shift' on hover to create a nice hover effect...
    1 point
  12. Hello @louisstephens, first of all great that you are giving UIkit a chance. I am coming from Bootstrap as well but UIkit is now my favorite framework so far. Here are a few points you mixed up: If you only have one item in a container you don't need a grid and instead can just use the uk-width-* classes. The class uk-grid-match is used for cards and makes your image stretched. Also it is not necessary if you only have one item. You should remove it. If you have a grid you should either define uk-child-width-* classes or assign uk-width-* classes to the items. Doing both is not very clean. If you care about validation, you should use data-uk-grid instead of uk-grid. Without the data attribute you get an error in the validation. Considering your logo: Even resized it will be very small on mobile devices. You should either think about a more compact logo or work with the picture element to show optimized versions. Regards, Andreas
    1 point
×
×
  • Create New...