Leaderboard
Popular Content
Showing content with the highest reputation on 11/29/2016 in all areas
-
Saw this on ghacks.net. I've never seen a conversion site so comprehensive. https://gchq.github.io/CyberChef/cyberchef.htm5 points
-
In memory search is only possible if the to be searched element is already retrieved, which means only if you call find on a PageArray. You're calling find on a Page object, which is just syntax sugar for $pages->find("parent=$booking, …") . I'd suggest you using https://blackfire.io/ for profiling. It's the best tool to look into the system I've ever used. With few parts of ProcessWire being called all over the place it requires a bit searching to find the exact part of code you actually can improve on, but it's worth for not needing to guess. To improve on plain query count (not necessarily speed) you go this way: $bookings = $pages->get('/bookings/')->find('room=roomOne'); // 2 queries foreach($bookings as $booking) $roomData = $booking->find('date=' . $today); // n queries // Improved $bookings = $pages->find('parent=/bookings/, room=roomOne'); // 1 query $roomsData = $pages->find("parent=$bookings, date=$today"); // 1 query foreach($bookings as $booking) $roomData = $roomsData->find("parent=$booking"); Edit: Just to add this here. Doing database queries in foreach loops is almost always to be avoided.5 points
-
New website for Fabrica Captial – Commercial Real Estate Investment http://fabrixcap.com/ (previously at http://www.fabricacapital.com/) Design by http://crookdesign.co.uk/4 points
-
That's mostly because it's not a simple problem to solve at all. Merging of changes happening in two independent systems cannot work simply by clicking a button. There are various ways to make it work, which all come with their own kind of backdraws. With each project having different goals/needs it's a matter if choosing the one giving you the least pains, while helping you enough to make it worth. Also I'm not sure if I missed some beta statement in my modules topic, but it's really stable. Any upcoming changes should only affect the accompanied cli tool. Also I've it in production usage for over a year now with no issues in the latest months.4 points
-
Database. If it was an in-memory query, the first find() operation would need to return every single child page along with the pages actually matching the query. I don't know anything about your structure, but it appears that you have "room pages" below /bookings/ and each room page has a variable number of booking pages as it's direct children, right? In the first query, if you're only interested in the direct children of /bookings/, you should use children() instead of find(). You should get a notable speed bump from this alone. Additionally: while this is probably not production code, please note that with every find() operation that has the potential to match a large number of results you should use limit, or otherwise you'll risk running into both performance and memory issues at some point.4 points
-
Hello member, I just install processwire and hopefully I can learn more from this forum.3 points
-
It’s ironic that they release this tool on the day the Snooper's Charter law became official in the UK. The new surveillance law (Investigatory Powers Act) requires web and phone companies to store everyone’s web browsing histories for 12 months and give 48 official groups full access to the data - one of these groups is the GCHQ. These groups will also gain new powers to officially hack into computers and phones to collect communications data in bulk. http://www.wired.co.uk/article/ip-bill-law-details-passed3 points
-
Are you running PW 3? In that case, make sure you use the FieldtypePDF module downloaded from the devns branch at github, not the one in the modules repo.3 points
-
I believe that each time you call $pages->find() or $page->find() the PageFinder class is used to query the database. If you're wanting to analyse performance in detail then Profiler Pro in the new ProDevTools would probably be money well spent. Besides the tool itself there is this benefit:3 points
-
Hello @Marcel Stäheli, maybe the console of your developer tools will reveal more information about the errors. Also you could turn on debug mode. It is not recommended to delete anything inside the /wire/ directory. Especially if you want to upgrade PW, it would just override any changes you have made. Regards, Andreas2 points
-
Made by Government Communications Headquarters in the UK.2 points
-
Really? There's only 2 and they are both maintained... Welcome to the forums2 points
-
You might want to remove the beta status. No software is perfect, however if it is stable, why not give it 1.0.0?2 points
-
I'm still in the middle of an almost complete rewrite. I still plan to have it finished by Christmas, but I don't dare to give a more precise estimate right now. As soon as that's finished, I'll release it as a beta and do some heavy-load testing in our intranet to confirm its stability.2 points
-
Right now, I use rsync for code deployement and about to install a bash script running mysqldump and mysql for DB backup and deployment. I run Procache so in the midst of writing some php modules that reconfigure the site from Dev to Prod. Hopefully I'll have a script that ties everything together soon. If this is of interest to anyone, I could post it once I'm sufficiently happy with it?2 points
-
Welcome @handzain. This is a very friendly and helpful community. I believe you will get much help here like I did. Gideon2 points
-
Just because a page happens to be linked only in the footer it's probably not supposed to be nested in the page tree. ProcessWire does hold pages in a hierarchical structure, which does not necessarily correspond to all the various navigational patterns used throughout the page. I'd just add those pages as "hidden" children of home. Hidden because they're not part of the primary navigation, but the are still direct children of home (think of the breadcrump you'd have for that page). For building the footer menu I'd just hardcode that one in the template or use some of the few menu builder tools available for ProcessWire.2 points
-
Humanity should stop the "Internet of things" madness before it is too late:2 points
-
This should be Paths.php, not Path.php right? It looks like something assigned an array to $config->paths->something. Dumping $key might get you on the right track of which "something" holds the array value PW complains about.2 points
-
2 points
-
@thlinna I have been working on a module, a more non-dev-friendly approach the migrations module for about one year (on/off). I am actually using it all the time but it's not ready for public. It has many bugs I know how to circumvent and next to no documentation. It's similar to JSON Installer module, but more powerful and the data files are written in YAML. Perhaps JSON Installer can be of help to you.2 points
-
Menu Builder As of 29 December 2017 ProcessWire versions earlier than 3.x are not supported Modules Directory Project Page Read Me (How to install, use, etc..) For highly customisable menus, please see this post. If you want a navigation that mirrors your ProcessWire page tree, the system allows you to easily create recursive menus using either vanilla PHP or Soma's great MarkupSimpleNavigation. In some cases, however, you may wish to create menus that: 1. Do not mirror you site's page tree (hirarchies and ancestry); and 2. You can add custom links (external to your site) to. That is primarily where Menu Builder comes in. It is also helpful if you: 3. Prefer creating menus via drag and drop 4. Have a need for menus (or other listings) that will be changing regularly or that you want to allow your admin users to edit. The issue of custom menus is not new here in the forums. The difference is that this module allows you to easily create such menus via drag and drop in the Admin. Actually, you can even use it to just create some list if you wanted to. In the backend, the module uses the jQueryUI plugin nestedSortable by Manuele J Sarfatti for the drag and drop and is inspired in part by the WP Custom Menu feature. Please read the Read Me completely before using this module. For Complex or highly-customised menus, it is recommended to use the getMenuItems() method as detailed in this post. Features Ability to create menus that do not mirror your ProcessWire Page Tree hierarchy/structure Menus can contain both ProcessWire pages and custom links Create menu hierarchies and nesting via drag and drop Easily add CSS IDs and Classes to each menu item on creating the menu items (both custom and from ProcessWire pages) or post creation. Optionally set custom links to open in a new tab Change menu item titles built from ProcessWire pages (without affecting the original page). E.g. if you have a page titled 'About Us' but you want the menu item title to be 'About' Readily view the structure and settings for each menu item Menus stored as pages (note: just the menu, not the items!) Menu items stored as JSON in a field in the menu pages (empty values not stored) Add menu items from ProcessWire pages using page fields (option to choose between PageAutocomplete and AsmSelect [default]) or a Selector (e.g. template=basic-page, limit=20, sort=title). For page fields, you can specify a selector to return only those specified pages for selection in the page field (i.e. asm and autocomplete) For superusers, optionally allow markup in your menu titles, e.g. <span>About</span> Menu settings for nestedSortable - e.g. maxLevels (limit nesting levels) Advanced features (e.g. add pages via selector, menu settings) currently permissible to superadmins only (may change to be permission-based) Delete single or all menu items without deleting the menu itself Lock down menus for editing Highly configurable MarkupMenuBuilder - e.g. can pass menu id, title, name or array to render(); Passing an array means you can conditionally manipulate it before rendering, e.g. make certain menu branches visible only to certain users [the code is up to you!] Optionally grab menu items only (as a Menu object WireArray or a normal array) and use your own code to create custom highly complex menus to meet any need. More... In the backend, ProcessMenuBuilder does the menu creation. For the frontend, menus are displayed using MarkupMenuBuilder. Credits In this module's infancy (way back!), I wanted to know more about ProcessWire modules as well as improve my PHP skills. As they say, what better way to learn than to actually create something? So, I developed this module (instead of writing PW tutorials as promised, tsk, tsk, naughty, naughty!) in my own summer of code . Props to Wanze, Soma, Pete, Antti and Ryan whose modules I studied (read copied ) to help in my module development and to Teppo for his wonderful write-up on the "Anatomy of fields in ProcessWire" that vastly improved my knowledge and understanding of how PW works. Diogo and marcus for idea about using pages (rather than a custom db table), onjegolders for his helpful UI comments, Martijn Geerts, OrganizedFellow, dazzyweb and Mike Anthony for 'pushing me' to complete this module and netcarver for help with the code. Screens1 point
-
LimitRepeater Allows restrictions and limits to be placed on Repeater fields. For any Repeater field you can limit the number of items that may be added and also prevent the use of drag-sorting, toggling of published state, and the trashing of items. There is also an option to hide the clone button when the limit is reached. Usage Install the LimitRepeater module. Since v0.2.0 the module settings are configured at Setup > Fields > [your Repeater field]. The settings are contained within the "Restrictions" fieldset on the "Details" tab. Please note that the restrictions limits are applied in Page Edit with CSS/JS so should not be considered tamper-proof. Setting restrictions via a hook Besides setting restrictions in the field settings, you can also apply or modify restrictions by hooking LimitRepeater::checkRestrictions. This allows for more focused restrictions, for example, applying restrictions depending on the template of the page being edited or depending on the role of the user. The checkRestrictions() method receives the following arguments: $field This Repeater field $inputfield This Repeater inputfield $page The page that is open in ProcessPageEdit The method returns an array of restrictions for the Repeater field. An example of a returned array: Example hook Prevent non-superusers from trashing any items in "my_repeater_field": $wire->addHookAfter('LimitRepeater::checkRestrictions', function(HookEvent $event) { $field = $event->arguments('field'); $restrictions = $event->return; if($field->name === 'my_repeater_field' && !$this->user->isSuperuser()) { $restrictions['notrash'] = true; } $event->return = $restrictions; }); Upgrading from < v0.2.0 There are two major changes to be aware of when upgrading from earlier versions of the module. The settings are no longer defined on the module config page, but rather in the field settings of each Repeater field: Setup > Fields > [your Repeater field]. If you visit the module config page you'll find shortcuts to the settings for each Repeater field. In earlier versions you could apply restrictions to a particular role. This is still possible but is now handled by hooking LimitRepeater::checkRestrictions as this is a more flexible and powerful approach. If you were applying restrictions to a particular role or roles you'll need to add hook code to achieve the same effect after you upgrade the module. See the hook information above in this readme. https://github.com/Toutouwai/LimitRepeater http://modules.processwire.com/modules/limit-repeater/1 point
-
Hi everyone, Here's a new module that lets you control whether multi-language support is enabled at the page / branch level, rather than only per template. http://modules.processwire.com/modules/restrict-multi-language-branch/ https://github.com/adrianbj/RestrictMultiLanguageBranch This is ideal for a site with repeated branches using the same templates where only some need to be multi-language. I think it is confusing to provide multiple language inputs for fields when they are not required - it just bloats the admin interface for site editors. I am hoping to expand this module to allow selection of which languages are supported per page/branch, but I am waiting on @ryan's response to this request: https://github.com/processwire/processwire-requests/issues/54 - to me this would be even more powerful if you have a situation where certain branches need some languages and other branches need different languages. The module config settings shows a summary of the restrictions you have implemented, eg: This shows that we have started with the home page which disables multi-language on itself and all its children/grandchildren (because "This Page Only" is "False". Next we have the /report-cards/ page multi-language enabled, but no inheritance (because "This Page Only" is "True"). The only branch below this to have multi-language enabled is Guanabara Bay and all it's children etc will also be enabled. All other report card branches will be disabled because they will inherit directly from the config settings default status. The Settings tab for each page gives you three options: Inherit, Enabled, Disabled. The screenshots give you an idea of how the Inherit option works and the information it provides based on the status it is inheriting and from where. My goal for this site was to just enable multi-language support for the Guanabara Bay report card branch of the tree, as well as the home page and the /report-cards/ parent. All other branches have multi-language support disabled which makes content entry much cleaner. Hope you guys find a good use for it and I'll be sure to update with the ability to define which languages are available on which pages/branches if Ryan comes up with a core solution for changing the returned $languages. Please let me know if you have any problems / suggestions.1 point
-
In this tutorial I will cover how to use clsource's REST Helper classes to create a RESTful API endpoint within a PW-powered site and how to connect to it from the outside world with a REST client. This is a quite lengthy tutorial. If you follow all along and make it through to the end, you should get both, a working REST API with ProcessWire and hopefully some more basic understanding how these APIs work. As always with PW, there are many ways you could do this. My way of implementing it and the code examples are loosely based on a real world project that I am working on. Also, this is the first tutorial I am writing, so please bear with me if my instructions and examples are not that clear to understand. And please let me know if something is missing or could be made more clear. The steps covered: create templates and pages in the PW backend to get an API endpoint (an URL where the API can be accessed at) copy and save the REST Helper classes to your site create a template file and write some logic to receive and process data through our endpoint and send data back to the REST client test the whole setup with a Browser REST Client Addon I will not go into fundamentals and technical details on how RESTful APis are supposed to work. I assume that you have already read up on that and have a basic understanding of the principles behind that technology. Some helpful resources to brush up your knowledge: https://en.wikipedia.org/wiki/Representational_state_transfer http://www.restapitutorial.com/lessons/whatisrest.html The complete pages.php template is attached to this post for copy/paste. Lets get started. 1. create templates and pages in the PW backend to get an API endpoint (an URL where the API can be accessed) First we need to create some templates and pages in the PW backend to make our REST API accessible from the outside world through an URL (API endpoint). In my example this URL will be: https://mysite.dev/api/pages/ Note the "https" part. While this is not mandatory, I strongly recommend having your API endpoint use the https protocol, for security reasons. Further down in step 3 we will use this URL to create new pages / update and get data of existing pages. Go to your PW test site admin and: create 2 new templates: one is called "api", the other one "pages". For a start, they both have only a title field assigned. Just create the templates. We will create the corresponding files later, when we need them. enable "allow URL segments" for the "pages" template. We will need this later to access data sent by the requests from the client. in the Files tab of the "pages" template check "Disable automatic append of file: _main.php" create a new page under the home page with title, name and template "api" and set it to hidden create a child page for the "api" page with title, name and template "pages" The pagetree should look somewhat like this: Ok, now we're all set up for creating our API endpoint. If you browse to https://mysite.dev/api/pages/ you will most likely get a 404 error or will be redirected to your home page as we do not have a template file yet for the "pages" template. We will add that later in step 3. 2. copy and save the REST Helper classes to your site I have the REST Helper class sitting in site/templates/inc/Rest.php and include it from there. You could save it in any other location within your site/templates folder. I forked clsource's original code to add basic HTTP authentication support. Click here to open my raw gist, copy the contents and save them to /site/templates/inc/Rest.php In the next step we will include this file to make the classes "Rest" and "Request" available to our template file. 3. create a template file and write some logic to receive and process data through our endpoint and send data back to the client This will be the longest and most complex part of the tutorial. But I will try to present it in small, easy to follow chunks. Since we access our API at https://mysite.dev/api/pages/, we need to create a template file called "pages.php" for our "pages" template and save it to /site/templates/pages.php. Go ahead and create this file (if you're lazy, copy the attached file). Now right at the top of pages.php, we start with <?php require_once "./inc/Rest.php"; to include the REST Helper classes. Next, we initialize some variables that we will keep using later on // set vars with the default output $statuscode = 200; $response = []; $header = Rest\Header::mimeType('json'); 3.1 retrieve data with a GET request Now that we have the basics set up, we will next create the code for handling the easiest request type, a GET request. With the GET request we will ask the API to return data for an existing page. To let the API know which page it should return data for, we need to send the page id along with our request. I am attaching the page id as an url segment to the API endpoint. So the URL that the client will use to retrieve data for a page will look like: https://mysite.dev/api/pages/1234 where 1234 is the unique page id. Add following code to pages.php // if we have an urlsegment and it is a numeric string we get data from or update an existing page: handle GET and PUT requests if($input->urlSegment1 && is_numeric($input->urlSegment1)) { $pageId = $input->urlSegment1; // GET request: get data from existing page if(Rest\Request::is('get')) { // get the page for given Id $p = $pages->get($pageId); if($p->id) { $pdata = ["id" => $pageId]; // array for storing page data with added page id $p->of(false); // set output formatting to false before retrieving page data // loop through the page fields and add their names and values to $pdata array foreach($p->template->fieldgroup as $field) { if($field->type instanceof FieldtypeFieldsetOpen) continue; $value = $p->get($field->name); $pdata[$field->name] = $field->type->sleepValue($p, $field, $value); } $response = $pdata; } else { //page does not exist $response["error"] = "The page does not exist"; $statuscode = 404; // Not Found (see /site/templates/inc/Rest.php) } } } else { // no url segment: handle POST requests } // render the response and body http_response_code($statuscode); header($header); echo json_encode($response); Lets brake this down: First we check for a numeric url segment which is our $pageId. Then the Rest Request class comes into play and checks what type of request is coming in from the client. For the GET request, we want to return all data that is stored for a page plus the page id. This is all good old PW API code. I am using the $pdata array to store all page data. Then I am handing this array over to the $response variable. This will be used further down to render the JSON response body. If the page does not exist, I am setting an error message for the $response and a status code 404 so the client will know what went wrong. The else statement will later hold our POST request handling. The last 3 lines of code are setting the header and status code for the response and print out the response body that is sent back to the client. You can now browse to https://mysite.dev/api/pages/1 where you should see a JSON string with field names and values of your home page. If you enter a page id which does not exist you should see a JSON string with the error message. Lets move on to updating pages through a PUT request 3.2 update pages with a PUT request Since our API needs to know the id of the page we want to update, we again need to append an id to our endpoint url. In this example we will update the title and name of our homepage. So the request url will be: https://mysite.dev/api/pages/1. For the GET request above, anyone can connect to our API to retrieve page data. For the PUT request this is not a good idea. Thus we will add basic authentication so that only authorized clients can make updates. I use basic HTTP authentication with username and password. In combination with the https protocol this should be fairly safe. To set this up, we need an API key for the password and a username of our choosing. We add the API key in the PW backend: add a new text field "key" and assign it to the "api" template. edit the "api" page, enter your key and save. (I am using 123456 as key for this tutorial) Now add following code right after the if(Rest\Request::is('get')) {...} statement: // PUT request: update data of existing page if(Rest\Request::is('put')) { // get data that was sent from the client in the request body + username and pass for authentication $params = Rest\Request::params(); // verify that this is an authorized request (kept very basic) $apiKey = $pages->get("template=api")->key; $apiUser = "myapiuser"; if($params["uname"] != $apiUser || $params["upass"] != $apiKey) { // unauthorized request $response["error"] = "Authorization failed"; $statuscode = 401; // Unauthorized (see /site/templates/inc/Rest.php) } else { // authorized request // get the page for given Id $p = $pages->get($pageId); if($p->id) { $p->of(false); $p->title = $sanitizer->text($params["title"]); $p->name = $sanitizer->pageName($params["name"]); $p->save(); $response["success"] = "Page updated successfully"; } else { // page does not exist $response["error"] = "The page does not exist"; $statuscode = 404; // Not Found (see /site/templates/inc/Rest.php) } } } Breakdown: We check if the request from the client is a put request. All data that was sent by the client is available through the $params array. The $params array also includes $params["uname"] and $params["upass"] which hold our API user and key. We set API key and user and check if they match with the values that were sent by the client. If they don't match we store an error message to the response body and set the appropriate status code. If authentication went through ok, we get the page via PW API and update the values that were sent in the request body by the client. Then we put out a success message in the response body. If the page does not exist, we send the appropriate response message and status code, just like in the GET request example above. Now you might wonder how the client sends API user/key and new data for updating title and name. This is covered further down in step 4. If you want to test the PUT request right now, head down there and follow the instructions. If not, continue reading on how to setup a POST request for creating new pages. 3.2 create new pages with a POST request Final part of the coding part is creating new pages through our API. For this to work we need to implement a POST request that sends all the data that we need for page creation. We will do this at our endpoint: https://mysite.dev/api/pages/ Paste following code within the else statement that has the comment "// no url segment: handle POST requests": // POST request: create new page if(Rest\Request::is('post')) { // get data that was sent from the client in the request body + username and pass for authentication $params = Rest\Request::params(); // verify that this is an authorized request (kept very basic) $apiKey = $pages->get("template=api")->key; $apiUser = "myapiuser"; if($params["uname"] != $apiUser || $params["upass"] != $apiKey) { // unauthorized request $response["error"] = "Authorization failed"; $statuscode = 401; // Unauthorized (see /site/templates/inc/Rest.php) } else { // authorized request // create the new page $p = new Page(); $p->template = $sanitizer->text($params["template"]); $p->parent = $pages->get($sanitizer->text($params["parent"])); $p->name = $sanitizer->pageName($params["name"]); $p->title = $sanitizer->text($params["title"]); $p->save(); if($p->id) { $response["success"] = "Page created successfully"; $response["url"] = "https://mysite.dev/api/pages/{$p->id}"; } else { // page does not exist $response["error"] = "Something went wrong"; $statuscode = 404; // just as a dummy. Real error code depends on the type of error. } } } You already know what most of this code is doing (checking authorisation etc.). Here's what is new: We create a page through the PW API and assign it a template, a parent and basic content that was sent by the client. We check if the page has been saved and update our response body array with a success message and the URL that this page will be accessible at through the API for future requests. The client can store this URL for making GET or PUT requests to this page. If you're still reading, you have made it through the hard part of this tutorial. Congratulations. Having our code for reading, updating and creating pages, we now need a way to test the whole scenario. Read on to find out how this can be done. 4. test the whole setup with a Browser REST Client Addon The link in the heading will take you to a place from which you can install the very useful RESTClient addon to your favorite browser. I am using it with Firefox which is still the dev browser of my choice. Open a RESTClient session by clicking the little red square icon in the browsers addon bar. The UI is pretty straightforward and intuitive to use. 4.1 test the GET request Choose Method GET and fill in the URL to our endpoint. If you do not have a SSL setup for testing, just use http://yourrealtestdomain.dev/api/pages/1. If you happen to have a SSL test site with a self signed certificate, you need to point your browser to the URL https://yourrealtestdomain.dev/api/pages/ first in your test browser and add the security exception permanently. Otherwise RESTClient addon won't be able to retrieve data. If you have a test site with a 'real' SSL certificate, everything should be fine with using the https://... URL Hit send. In the Response Headers tab you should see a Status Code 200 and in the Response Body tabs a JSON string with data of your page. now change the 1 i the URL to some id that does not exist in your site and hit send again. You should get a 404 Status Code in the Response Headers tab and an error message "{"error":"The page does not exist"}" in the Response Body (Raw) tab. If you get these results, congrats! The GET request is working. For further testing you can save this request through the top menu Favorite Requests->Save Current Request. 4.1 test the PUT request Choose Method PUT and fill in the URL to our endpoint ending with 1 (http://yourrealtestdomain.dev/api/pages/1). In the top left click Headers->Content-Type: application/json to add the right content type to our request. If you miss this step, the request will not work. You will now see a "Headers" panel with all your headers for this request Click on Authentication->Basic Authentication. In the modal window that pops up, fill in user (myapiuser) and password (your API key). Check "Remember me" and hit Okay. You now should see Content-Type and Authorization headers in the "Headers" panel. Next, we need to send some data in the request body for updating our page title and name. Since we're using JSON, we need to create a JSON string that contains the data that we want to send. As I will update the home page for this example, my JSON reads { "title" : "Newhome", "name" : "newhome" } Be careful that you have a well formed string here. Otherwise you will get errors. Paste this into the "Body" panel of the REST Client addon. Hit send. In the Response Headers tab you should see a Status Code 200 and in the Response Body tabs a JSON string "{"success":"Page updated successfully"}". Now go to the PW backend and check if title and name of your page have been updated. If yes, congrats again. 4.2 test the POST request Choose Method POST and fill in the URL to our endpoint without any page id (http://yourrealtestdomain.dev/api/pages/). In the top left click Headers->Content-Type: application/json to add the right content type to our request. If you miss this step, the request will not work. You will now see a "Headers" panel with all your headers for this request Click on Authentication->Basic Authentication. In the modal window that pops up, fill in user (myapiuser) and password (your API key). Check "Remenber me" and hit Okay. You now should see Content-Type and Authorization headers in the "Headers" panel. Next, we need to send some data in the request body for updating our page title and name. Since we're using JSON, we need to create a JSON string that contains the data that we want to send. I will create a new page with template basic-page and parent /about/ for this example, my JSON reads { "template" : "basic-page", "parent" : "/about/", "title" : "New Page created through api", "name" : "newapipage" } Be careful that you have a well formed string here. Otherwise you will get errors. Paste this into the "Body" panel of the REST Client addon. Hit send. In the Response Headers tab you should see a Status Code 200 and in the Response Body tabs a JSON string "{"success":"Page created successfully","url":"https:\/\/mysite.dev\/api\/pages\/1019"}". Now go to the PW backend and check if title and name of your page have been updated. If yes, you're awesome! Summary By now you have learned how to build a simple REST API with ProcessWire for exchanging data with mobile devices or other websites. Notes I tested this on a fresh PW 2.7.2 stable install with the minimal site profile and can confirm the code is working. If you experience any difficulties in getting this to work for you, let me know and I will try to help. There purposely is quite a lot of repetion in the example code to make it easier to digest. In real life code you might not want to use procedural coding style but rather separate repeating logic out into classes/methods. Also, in life applications you should do more sanity checks for the authentication of clients with the API / for the data that is delivered by the client requests and more solid error handling. I skipped these to make the code shorter. RESTful services are by definition stateless (sessionless). My implementation within PW still opens a new session for each request and I haven't found a way around that yet. If anyone can help out this would be much appreciated. And finally big thanks to clsource for putting the Rest.php classes together. pages.php.zip1 point
-
Hey @kongondo I just recently came across this module in a existing PW project I had to take over. I knew about it's existence but never tried it myself. Great and useful features, thanks!1 point
-
Just adding Ryan's answer from the Github issue for future reference:1 point
-
1 point
-
@elabx, the unformatted value of an images field is always a WireArray. Having the value be a Pageimage for a single image field is the result of output formatting. I think what Soma is saying above is that output formatting is off when you bootstrap the PW index.php. So the issue doesn't occur because of an AJAX call, it occurs because of the bootstrapping. So solutions would be either: Just be aware that output formatting is off when bootstrapping PW and adjust your code accordingly In your AJAX call, load a normal PW page rather than a PHP file that bootstraps index.php1 point
-
I'm nor sure anymore how that admintheme error happend, I think i read an outdated thread on how to customzite it. I copied the AdminTheme Folders from a diffrent project where everything was fine. Still had the problem, then I copied the \wire\templates-admin folder, and that did the trick.Everything is back to normal. Lesson: Never mess with the wire folder. Thanks, I don't think I would have tried that without your input.1 point
-
v107 is up, containing a new feature for pagelist items: "Use middle mouse click/ctrl+click to View/Edit page".1 point
-
CroppableImages uses the core images rendering engines. So there is no special "Croppable image rendering". Your original image left is very blurry, and the one on the right site is much to much sharpened. Please try a variation with sharpening soft or none.1 point
-
I'm based in Berlin at the moment .... there's always enough Devs for a meetup1 point
-
Looking at this, it's got a lot of what I needed! I added a few other little features, but thank you for this code! It's been very helpful! @adrian I never would've found this on my own - thank you!! I never would've been able to see how Process modules worked without this file, either: https://github.com/ryancramerdesign/ProcessHello/blob/master/ProcessHello.module.php Lastly, here's the repo for the module I made - I'd love any feedback (There are definitely some janky bits)! https://github.com/ethanbeyer/ProcessWire-Blacklisted-Page-Names-Module1 point
-
This is not a bad idea, I'd like to see a tutorial/guide of how to implement a REST API with common best practices and possibly the correct way of getting the image/repeater fields and show how to use query selectors with limits, pagination etc.1 point
-
@szabesz sometimes live changes break the existing site if you don't have the necessary files (e.g. template files). Also, working on a live site's structure ... breaking stuff. Rather locally. It's kind of cumbersome, but this is how I do it: I lock the site for edits (in consultation with the client of course), clone the db, make changes locally and update the db when finished. Here's a small recipe for adding a maintenance mode.1 point
-
@thlinna I do not know if it will be of any help, but I myself do not migrate any db at all. Instead I build my workflow around this: http://tltech.com/info/mysql-via-ssh/ I put together a bash script to completely automate the process, and normally I can clone the live db to my local machine in seconds (small databases...). This way I always have to work on the live site to make all the necessary changes, afterwards I have to clone the db, but it is an easy to follow workflow and dead simple It might be too simple for teams, but a solo developer cannot go wrong with it, at least I'm quite happy with it, I got used to working this way. Sure, I have never had to work with really big databases, but these days even transferring dozens of megabytes does not take long.1 point
-
For future reference, only for front end though (as far as I'm aware of, because you output it slightly differently) there's field rendering template files https://processwire.com/blog/posts/more-repeaters-repeater-matrix-and-new-field-rendering/#processwire-3.0.5-introduces-field-rendering-with-template-files https://processwire.com/blog/posts/processwire-3.0.7-expands-field-rendering-page-path-history-and-more/#field-rendering-with-template-files they can be a nice alternative for textformatters at least front-end wise, and maybe easier for newcomers1 point
-
Ok, so I've gone for this approach. My images are being created in a few places and the templates are getting a bit unruly, so I thought I'd get this into a function. Of course, any improvements I can make are appreciated. The function and new news-index.php look like this now. // _func.php /** * * @param PageID $item * @param $img string (medium, large, xLarge) * @return $imgUrl string * */ function getImage($item, $img) { if ($item->mainImage) { switch ($img) { case 'medium': $img = $item->mainImage->size(750, 250, 'center'); break; case 'large': $img = $item->mainImage->size(1500, 500, 'center'); break; case 'xLarge': $img = $item->mainImage->size(2400, 800, 'center'); break; } $imgUrl = $img->url; return $imgUrl; } } // news-index.php <?php $entries = $pages->find("template=news-entry, limit=6, sort=-sort"); $firstItem = $entries->first(); $otherItems = $entries->not("$firstItem"); $pagination = $entries->renderPager(); $firstItemPublishDate = date('d/m/y', $firstItem->created); $firstItemCreatedBy = $firstItem->createdUser->displayName; ?> <style type="text/css"> .large-image-wrapper { background-image: url('<?php echo getImage($firstItem, 'medium'); ?>'); } @media screen and (min-width: 850px and max-width: 1499px) { .large-image-wrapper { background-image: url('<?php echo getImage($firstItem, 'large'); ?>'); } } @media screen and (min-width: 1500px) { .large-image-wrapper { background-image: url('<?php echo getImage($firstItem, 'xLarge'); ?>'); } } </style> <div class='large-image-wrapper'> <div class='title-wrapper'> <h1><a href='<?php echo $firstItem->url; ?>'><?php echo $firstItem->title; ?></a></h1> <?php if ($firstItem->summary) { echo $firstItem->summary; } ?> <div class='entry-info'> <span class='fa fa-calendar' aria-hidden='true'></span> Posted by <span class='entry-highlight'><?php echo $firstItemCreatedBy; ?></span> on <span class='entry-highlight'><?php echo $firstItemPublishDate; ?></span> </div> </div> </div> <div id="page-tabs-wrapper"> <div class='page-tabs'> <div class='upper'> <?php echo $pagination; ?> </div> </div> </div> <div id='news-row'> <?php foreach ($otherItems as $entry): ?> <?php $publishDate = date('d/m/y', $entry->created); $createdBy = $entry->createdUser->displayName; ?> <div class='news-column news-column-left'> <div class='news-index-image-wrapper' style='background-image: url("<?php echo getImage($entry, 'medium'); ?>")'> <div class='news-index-title-wrapper'> <h2> <a href='<?php echo $entry->url; ?>'><?php echo $entry->title; ?></a> </h2> <div class='entry-info'> <span class='fa fa-calendar' aria-hidden='true'></span> Posted by <span class='entry-highlight'><?php echo $createdBy; ?></span> on <span class='entry-highlight'><?php echo $publishDate; ?></span> </div> </div> </div> </div> <div class='news-column news-column-right'> <?php if ($entry->summary) { echo $entry->summary; } ?> <?php if ($entry->body): ?> <p class='read-more'><a href='<?php echo $entry->url; ?>'>Read full article <span class='fa fa-arrow-circle-right' aria-hidden='true'></span></a></p> <?php endif; ?> </div> <?php endforeach; ?> </div> <div class='page-tabs'> <div class='lower'> <?php echo $pagination; ?> </div> </div> // _images.scss .large-image-wrapper { padding-top: 0; @include media($tablet) { padding: 75px 0; } @include media($hidpi) { padding: 150px 0; } background-position: center; background-repeat: no-repeat; background-size: cover; } I have set a default image as suggested by @Zeka (awesome feature!) and my max upload width is 2400px, with min also being 2400px. The biggest size image I will ever display is 2400px (the xLarge size will just be cropped in height). Next step is making '<?php echo $created_by; ?>' into a link which lists all news items posted by that user. Not sure whether I'll end up with a URL like site.com/news/username/ or site.com/user/news/ or whatever. Cross that bridge when I get to it. Seems to work ok so far though. I still like the fact that I can focus on the design so much better than I could in other CMS's I've used.1 point
-
I think in terms of building apis people just look at things like laravel which come with everything included: router, automatic post data parsing for json, rules where to put files and so on. Some things are nice to have like the automatic parsing of json if the post data come in as content-type: text/json, while in case of routing I'd keep that one for people to install manually. There are great 3rd party routers out there, so no need to have one in ProcessWire by default.1 point
-
I couldn't have said better myself This was the most important message I was trying to get through but I had been lost is some details, I suppose. Generally, the more options we have the better, but there is one thing that generates unnecessary extra work and that is being "non-multilanguage". By implementing something like this in the core, the question of "should it be multi-language or not" could be eliminated: While we are at it, @adrian's Admin's Restrict Branch module is based on similar principles, so maybe both could find its way into the core. Anyway, since the ProcessWire community mainly comprises developers who are already fine with the own way of building frontend from "scratch" (probably they use their own base profile or equivalent boilerplate), it is hard to see that without you leading the way such a community effort could be successful. Judging by the low number of responses to my proposal, current developers are not too interested...1 point
-
Dynamic Selects version 003 (released (27/11/2016)) Happy to announce that the latest release of Dynamic Selects is now available for Download/Purchase. IMPORTANT If you will be using this module in the frontend please FIRST READ at least the following topics in the documentation in their entirety. Security Settings Introduction to frontend use Example frontend use Debugging results in the frontend I have spent a considerable amount of time developing and testing security features to make using MarkupDynamicSelects safe. If you believe you've come across a potential vulnerability, I would appreciate it if you could send me a PM/email about it, thanks. @note: Currently, the Excluded Templates + Included Pages combo does not work as expected if you use more than one range of IDs for either. In such cases, please stick to comma-separated values. Changelog Frontend Dynamic Selects: Added Process- and MarkupDynamicSelects. Expanded included/excluded settings to cover templates and pages.1 point
-
Hello ProcessWire community, Here is my proposal: “ready-to-go profiles” Why more than one? Why not put all the effort into a sort of “standard” way of implementing the frontend. Something that is a versatile and officially supported way of building a site profile. Of course, it should not be forced upon anyone, so that the “blank profile” is always there for those interested. I’m not proposing to change the current philosophy, rather I suggest that we add an additional layer on top of it. There could be only two site profiles that comes with the system: blank and “community”. This so called “community” profile should be: Updatable by site owners in an automated fashion just like modules with the ProcessWireUpgrade module. Hookable, so that part(ial)s of it can be removed and added, meaning it can be changed to one’s needs in a way that is supported by the core. Well documented so that others can easily use it, contribute to it, and can implement custom “widgets” and/or partials that can be used by anyone. These so called ‘Widgets” (template partials / blocks / whatever we call them) would need to implement a standard interface so that the Widgets can be wired into the system no matter what sort of Templates and Fields are used by the backend. With a little bit of code (writing the proper selectors, etc..) the widgets could be wired up to the system, in an officially supported and documented way. This profile would come with standard blogging and portfolio-site like tools already implemented, ready to be used and extended. Any of the implemented features should be easily disabled, as opposed to all the “junk” that comes with WordPress for example (where implementing hooks are required to remove things like RSS, oEmbed, emoji, etc...) If there are features like these, site owners should be able to turn them on/off, nothing should be forced upon them. This site profile should also support something similar to the Css Zen Garden philosophy, so that not only widgets/blocks can be added/removed, but the profile can be “skinned”. These skins could be interchangeable. It would be multilanguage with features suggested by Adrian. To summarize: by working on only one but a versatile and updatable site profile, the whole ProcessWire community could add their bits to it, finally there could be a standard to which one can optionally adhere to. The backend could utilize the very same/similar methodology, so that the community site profile and the admin share the same grounds. It was already mentioned that the backend might introduce UIkit, so this site profile should be built upon it too. For example, imagine being able to utilize the ProcessWire form API on the frontend, fully supported by the site profile’s css framework! Those who use this “community” profile (or any other UIkit based profile they implement) could optionally share UIkit with the system too. I am one of those who would mainly stick to such a profile but it is easy to see how this would help beginners and professionals, and the ProcessWire project too. Cheers1 point
-
I used ProcessExportProfile in Processwire 3.0.3. The name fields can not have point character ".". If, than the site-profile is not detected. The generated config.php file needs the namespace at top, if generating new Classes in the config, like: <?php namespace ProcessWire; //... if(!defined("PROCESSWIRE")) die(); //... $config->custom_footer_scripts = new FilenameArray(); //own array for js at bottom of page I like ProcessExportProfile for new Projects — i hope the module is not buried.1 point
-
I'm new to processwire, but have some decent experience in Scala, python and others. I was the typical guy making fun of php. Processwire changed that, the api design is very elegant and convinced me. I can host the event in Berlin, so we have big monitors for everyone, projectors, etc. Ping me if you are interested. We can make it a mini conference, with speakers etc.1 point
-
I know someone has to write this, so let it be me. The first time I realised what I could do with the ProcessWire API it was like an insane mode in mentioned Tesla Model S. But it was just the beginning as PW keeps accelerating me ever since. Of course there are rough edges, but I am sure there are some in Tesla too - you just have to own it a bit longer to discover them . This creation of yours, Ryan, is something that was a mind-changer and a life-changer for so many of us here and more around the globe. And it is not just cheaper and better, it is open source and the best you can get! Tesla team made a great job. So did you - alone. More people everywhere in the world are using PW now than probably ever will be using Tesla cars. So the impact not only on the future, but on the present is quite comparable (Tesla team just has to work harder to not fall behind too far). ProcessWire is equally fine crafted mixture of technology and design, as this electric car... But none of us have to give it back some day soon. But not only the technology is to be mentioned. ProcessWire is a community, open source and global. People from Africa use it alongside people from Europe and Americas. And they (actually we) come together every day to talk to each other about a topic of no envy and hatred, but a common love and perspective. The world seems to be so unstable and fragmented these days. At the place that I live I hear a lot of negative words aimed at US and its policy. Some of it might be true, some of it is an obvious propaganda. But without other channels of information and communication you can easily lose your own point of view. I am sure something similar is happening on the so called "other side". Here in community we overcome that way of thinking. You, Ryan, and the open source ProcessWire thing is doing better job for creating a world as a better place than NSA spying scandals and troops being brought to places abroad for sure. And your avatar is the most friendly face of America to be seen for many. I do not know if making one of the best pieces of software in the world for free and inspiring one of the most friendly and helpful international communities shall ever help you to buy a luxury electric car (I really hope so), but "at least" your children have something to be really proud about.1 point
-
It occurred to me that a good addition to the forums would be some way for PW users to indicate support for a module idea. Similar to the Wishlist subforum but for functionality that belongs in a module rather than in the core. I'm thinking mainly of commercial modules, although if someone wanted to take up a module request and release it freely that would be cool. So users could propose a module idea, then others would vote for it (using likes or some special voting option) so that a vote means "I'd buy that", with the expectation of pricing in the general ballpark of Ryan's pro modules and Apeisa's PadLoper. As a beginner-intermediate developer I'm really enjoying working with PW and learning as I go - the API is so intuitive that I've been able to build my own solutions to things that in another CMS I would have been reliant on someone else's module to achieve. But there are things that I know are beyond my current skills, and for those things I look to third-party modules. My clients are non-profits and small businesses so I'm never likely to have the budget to commission a custom module alone. But there might be other PW users out there with similar needs and maybe that demand would make it worthwhile for an experienced developer to take on a proposal and release it as a commercial module. Currently there isn't a way to measure the demand for modules apart from occasional forum posts like "Is there a module that...?" Any thoughts on this? Here's a module request to start off with: I would be happy to buy a full-featured event calendar module. I've searched the module directory and the forums and Lindquist's module is the most feature-rich I've seen, but it's in an alpha proof-of-concept state and some important functions aren't implemented. Features I would be looking for are: Calendar grid interface in admin, allowing for easy addition and editing of events. (Nice but non-essential) Week and day views in admin, in addition to month view, with drag editing for event date and duration (I'm dreaming of something awesome like the dhtmlxScheduler interface or Fullcalendar interface). Although drag operations would really need an undo to correct accidental edits, so this may be more trouble than it's worth. Events are edited in a modal window, to avoid losing one's place in the calendar. Recurring events, with user-friendly selection of recurrence options. The ability to individually edit or remove an event that is a child of a recurring event (i.e. make an exception for that individual event). (Nice but non-essential) A couple of out-of-the-box minimal rendering options for the frontend (read-only calendar view, list view). This is the kind of module I need frequently. I've been lucky that I haven't had a client request a full event calendar since I've been using PW, but it's only a matter of time. I'm sure there are other PW users who need this and who would, like me, be happy to pay for such a module.1 point
-
I think this is good idea. Personally I have a number of module ideas but have no firm idea what to prioritise. Something like this would be of benefit to me. As for a calendar module, I have been working on something for a while now. These are very old screenshots and will change. The module was based on dhtmlxScheduler but that will definitely change. Maybe I should release this module next1 point
-
Successfully tested ALIF with PW 3.0 and set the version to 1.0.0 stable now.1 point
-
Looking at the function getRandom() this should work: $rndm = $pages->find('template=xxx, limit=40, sort=-created')->getRandom(4); 4 in this case being the number of random results you want to return, and note the minus before created else you'll be getting the first 40 created pages for the template instead of the last 40. The actual getRandom function is on line 368 of wire/core/Array.php EDIT: Just tested it on my install and it does work, pulling 4 random pages from the last 6 in my case (easier to debug as I can remember the last 6 I added ). The full code I used was this (my template was game in this case): $rndm = $pages->find('template=game, limit=6, sort=-created')->getRandom(4); foreach ($rndm as $pg) { echo $pg->title . "<br />"; }1 point