Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 01/02/2016 in all areas

  1. 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.zip
    16 points
  2. (Sorry, couldn't resist. English is such a wonderful language, don't you think?)
    5 points
  3. Happy New Year! Here's the ProcessWire 2016 roadmap: https://processwire.com/blog/posts/happy-new-year-heres-a-roadmap-for-processwire-in-2016/
    5 points
  4. Hello and happy new year to everybody This little module adds an unselect button to PageListSelect. You can define to which PageLists the button is added via module config (CSS selector). it solves this issue: https://processwire.com/talk/topic/9677-unselectclear-button-for-pagelistselect/ https://github.com/BernhardBaumrock/PageListSelectUnselectButton Changelog: v 2.0.0 - added support for ajax loaded fields including repeaters - added sanitization for the jquery selector
    4 points
  5. For people who want a simple solution out of the box, I would say ProcessWire is not that kind of CMS and that's a good thing. I see ProcessWire as a developer-oriented tool for building custom, complex content websites that have unique requirements and that should be it's strength. CraftCMS and ExpressionEngine fit that niche as well. If ProcessWire were to become a CMS where themes could be swapped at will, I'd imagine that would first pose some technical challenges that would need to be resolved. For example, to what extent does a theme dictate field/template structure, and if someone were to switch to another theme, how would that work? Nico's WireThemes proof of concept module has a nice way of going about that. It's similar to how FormBuilder can map a form's fields to a page's fields when using FormBuilders option to save submissions as pages. When it comes to WordPress and premium themes (like ThemeForest), once you're on a theme, you are stuck with it. No easy portability. Not to mention, each theme is like a CMS within WordPress itself, especially with the trend of mega themes that have recently become popular. Then when add a few plugins to the mix and you'll probably have all kinds of conflicts. Although WordPress is still the king of CMSes for ready-to-go themes, I would say that WordPress is going to be losing its dominance in that arena given the new generation of remotely hosted content management systems, like SquareSpace, Wix and Webflow. Those companies are doing very well because they really cater to people who want something up quick, cheap, easy and with a small learning curve. No coding required. It seems that WordPress (.com at least) is stepping up their game to challenge that. Their new admin system and Jetpack are good examples. Lastly, being the McDonalds of CMSs will cheapen the image of ProcessWire. I do think however we should be attracting advanced WordPress developers. In short, anyone who uses any tools from Roots.io, Underscores, Advanced Custom Fields, WP-CLI, or similar. There are many talented people in those circles who for reasons beyond me, still use WordPress.
    3 points
  6. Looking forward to finally getting the forums upgraded to 4.1 - just need to clear some work out of the way and we can get this done in Q1 easily enough, which is something of a necessity since the current version reaches end of support in June.
    3 points
  7. Great work Bernhard! I think this should be in the core!
    3 points
  8. This post has had an inexplicable surge of Likes over the past few weeks so there seems to be quite a bit of interest in this 7 months later. I've been unable to follow these concepts up with the time they deserve but those interested in an mage field tidy up can see Toms own beautiful work mentioned on the Dec 18 blog post. Furthermore, Ryan mentioned in today's Roadmap blog post that these (Tom's) designs are already being worked on by LostKobrakai. Exciting stuff!
    3 points
  9. i really liked the "save + new" and "save + close" button back in my joomla days here is the first version of a module to bring this functionality to processwire. i know there's the save actions module, but that's not exactly what i wanted... module is alpha state https://github.com/BernhardBaumrock/SaveButtonEnhanced i have one problem where i need your help: i want to submit the #ProcessPageEdit form via a jquery click() event: https://github.com/BernhardBaumrock/SaveButtonEnhanced/blob/master/SaveButtonEnhanced.module#L126 but unfortunately that does not submit the form reliably. sometimes it works, sometimes it doesn't. most of the time i need a second click. also i was not able to trigger the click like this: $('body').on('click', '.sbe_action', function() { console.log('clicked a sbe item'); }); it just did nothing does anyone know what is the problem here? would really appreciate it.
    2 points
  10. ** replaced with this: https://processwire.com/talk/topic/11817-module-adminhelp/ ** This is a new module, work in progress/alpha (not for use on live site): [github link deleted] AdminDocsTab module for ProcessWire Processwire helper modules for managing site documentation. Instructions This is a helper module which expects you to have already setup a hidden part of your page tree to establish your documentation, using any template (e.g. 'docs') and a body field (ckeditor). The docs template does not need to have an output template, as the module will only echo the body field inside the admin. In addition this 'docs' template will require a template select field (separate module: FieldtypeTemplates) which should be named template_select. Once you have setup your docs template, template_select field and some docs pages, you should install the AdminDocsTab module, then select the template(s) to show the docs on, as well as the root page of your docs. At this point the 'Docs' tab should show up for the relevant template (as specified in the Doc), and show the docs that have that template specified. To have a global docs overview page (e.g. 'Docs'), which renders all of the docs in an accordion view, you can install the ProcessDocsView module, which will setup a page to view the docs (under Setup).
    2 points
  11. So maybe this should be renamed and some of the wording changed for clarity - like AdminHelp instead of docs; as J. Lahijani brings up, what if you only want the main help page but not the help tab on the editor. So rethinking this setup to where there would be 3 modules: 1.) AdminHelp this would hold the settings for the AdminHelp sub-modules: - template being used for help pages (for sites with existing help pages) - root page of help pages it could possibly: - create the 'help' and 'help-index' templates if not found, and add the title and body fields and set the family rules. - create a default help page. 2.) AdminHelpTab - requires the FieldtypeTemplates and AdminHelp modules. - creates the field for the template_select on the template that is specified in the main module, and add it to that template; - holds the setting for which templates to allow help tab on - handles hooking into the page editor and adding the Help tab, and the scoped CSS for the display of the help text. 3.) ProcessAdminHelp - requires AdminHelp module - handles creation and display of the main help page
    2 points
  12. Or you could use this undocumented feature: Edit your /site/config.php and set $config->advanced = true; In your admin, go to Setup > Templates > your-post-template Click to the "System" tab. See the last field: "Allow the created user to be changed on pages?" Check that box and Save. Restore your config.php back to normal: Edit your /site/config.php again and set $config->advanced = false. Now you should be able to change the "Created User" on the Settings tab of any pages using that template.
    2 points
  13. As described in this post (https://processwire.com/talk/topic/8551-custom-urls-for-pages/?p=82742) the option 'Name Format Children' under the tab 'Family' in template settings doesn't work properly and also not as expected. I had a look inside the code and made some changes which are working properly, which offers much more options, more consistency and less code too. The result is the following. You have 3 Options for generating name and title, which could be combined in endless variations. Name is always derived from title, same like creating pages manually. type date: if function detects # character anywhere in the string, conversion will be: deletion of # and string will be used as format parameter for PHP date() function type field: if string is a fieldname of the parent page the value of this field will be used type string: if string doesn't fit to the 2 preceeding it will be taken as it is All parts (separated by comma) will be composed in the order of setting. You can use unlimited numbers of parts I made a pull request on github: https://github.com/ryancramerdesign/ProcessWire/pull/831 Example screenshots Setting ... will result in
    1 point
  14. This is a reworked website of Imre Baksa, a Hungarian actor and director. His former (static) website was also made by me back in around 2009. He asked me to do a redesign but I decided to involve ProcessWire to make content management easier. http://baksaimre.hu/ Lesson 1: templates - no thanks It is tempting to use ready-made templates for a project because most of the work is done, there's some tweaking here and there and mission completed. Okay, this is the theory. I have to admit that I have never found a suitable template/theme for my projects, but being a web designer this is the way it should be, I guess. This time I found one that looked fine: Landed from HTML5 UP. In fact there was a self-made design for the site and this template looked 90% similar, so it really seemed to be an easy task to bring it into ProcessWire. Soon turned out that some of the fancy features of the template required advanced JavaScript knowledge. That means, I had to dive into it and learn how it worked. I did so and I was able to tweak things then, but I wasn't satisfied with the outcome. So I went back to the drawing board and dropped the template. This experience reassured that starting from scratch would have been a better choice on the long run. The good thing is that I learned some new things that will come in handy in the future. Lesson 2: template engines - Latte is still my best friend I was using Nette's templating engine, Latte in previous projects and I liked it a lot. It is similar to Twig, which is more widespread, so I decided to try that for learning purposes. This sounded like an easy journey because ProcessWire supports Twig through modules. However, at the end of the day I sort of regretted that. Latte has some small helper features that makes templating easier, and these differences made up a huge difference. Maybe I'm getting old but I felt Twig more of a nuissance after Latte. Finally I got rid of Twig and I guess I will never look back I will keep using Latte in the future even if I have to bootstrap it manually. Lesson 3: frontend development is hard Having ProcessWire at hand, backend is the minor part in web development, at least in smaller projects. I've used only a few jQuery plugins but making them work together nicely was a real challenge. At the end I had to make a compromise by removing SmoothScroll because it didn't work well with JScrollPane. Even so, I had tough times to eliminate content "jumps" when a lightbox is opened, and to make JScrollPane work the way I wanted to work. Making the whole thing responsive added another level of complexity as features needed to be destroyed/reinitialized on different screen sizes. I like to polish things as much as possible but the current state of the web makes it almost impossible to reach certain level of perfection. Moduling up This was the project where I felt that a link checker button would be helpful so started to develop InputfieldURLChecker. I use this in a few projects and it does the job nicely. My other pet PW module FEEL also got some polish during site development. For site-wide settings I used MultiValueTextformatter so I didn't need to create a field for every setting, just one for all. Other modules used: SEO: must have! Admin Template Columns for better admin layout Page List Image Label: to add featured image to the list of pages in the admin Pageimage Remove Variations: remove unused image variations Forms: one step closer to simpler form processing For the contact form I used Nette Forms, because it is so easy to add forms to the site with it, with frontend & backend validation in one go. Processing them still needs some sweat, but this time I finally put together a class to make this easier. Surely it still needs some iterations but it's a huge help: it takes only a few parameters to save submissions as Pages or send email to the admin or the visitor. For email templates I also used Latte (what else? ). I also created a "json_storage" field to store submission. The beauty is that while it's only one field (a textarea), in the admin it is displayed as formatted key-value pairs using a hook. Summary The site looks fresh and the year knob on the left makes it fun to use. Content management is easy as 1-2-3 thanks to ProcessWire, even if it's mostly me who will deal with the updates. While it's not visible on the site, in the background there are many improvements to my development tools and workflow that will be of huge help in the future.
    1 point
  15. hi everyone, i'm happy to share my first little module that could have broader use... use at your own risk! i'm quite new to module development Usage Just install the module and place your preview images in the folder /site/templates/TemplatePreviewImages filename = template-name.png Github https://github.com/BernhardBaumrock/TemplatePreviewImages Notes jquery image picker used in this module (MIT license): http://rvera.github.io/image-picker/ Room for improvement / roadmap: Images are resized via CSS (height: 200px) Images could be placed via masonry or the like create image-field to upload preview images directly to the template looking forward to hearing your feedback ps: is it intentional that i am only allowed to choose from 2 templates when adding the page and have more options available when editing the template settings of the page like you can see in the video? i'm wondering why this should be like this?!
    1 point
  16. For question #1, there's a less complicated way to go about it. Create a Page field called "Favorites" (or "Subscriptions"). Templates allowed for this field should be: episode, series, and whatever else can be favorited. Add this Favorites field to the User template. Program the feature as needed. For question #2, the approach you outlined is pretty correct and the ProcessWire way of doing things (or you could also use Options Fieldtype, but I don't prefer it). I personally call it "Options" instead of "Tools" and pluralize the option types (Languages instead of Language, Durations instead of Duration). Then create Page fields as necessary.
    1 point
  17. i've implemented something like that today (alpha): https://processwire.com/talk/topic/11810-savebuttonenhanced
    1 point
  18. Thanks for updating the roadmap, and a Happy New Year to you too, Ryan! We've got some great things coming this year, no doubt about that Though we might want to discuss this eventually in a separate thread, inspired by Mike's comment above here are some initial comments regarding the site redesign. I'm trying to be as constructive as possible here, so please forgive me for just stating negative things; there's a lot of good too, but right now I feel that it's more useful to point out things that don't feel quite right. I've mentioned this before, but what I would love to see would be more clarity in regards to navigation and structure. For most parts those are the same thing, but there are also things that are only related to one. The visual side of the site could perhaps use a facelift too, but I wouldn't consider that a top priority right now; in my opinion there are more urgent issues to address, and the site doesn't feel all that outdated to be honest. Great design transcends time and so on Perhaps the biggest inconvenience for me is that the hierarchy of the site is not really reflected on the navigation. Topmenu items are not items at the top level of the page tree (except that some are), subnav items are often links to other sections of the site or completely separate (sub)sites, etc. One key strength of ProcessWire is the page tree approach, which makes structure sensible and easy to follow. I would like to see that benefit in action on our own site too. Other than that, I feel that the structure has pretty much grown in an organic way, and as a result of that things are not always where I'd expect to find them, and sometimes adjacent pages feel entirely different in scope. Some pages appear in multiple places, which can also get confusing, though in those cases they're usually redirects to somewhere else on the site. All in all the content architecture of the site doesn't feel very concise to me. In regards to the subnav, I would like to see some minor usability improvements in upcoming versions. For an example, the first item of the menu is actually the parent page, but visually it's in no way different from its children, which makes it less obvious than it could be. Also, while I still feel that a dropdown menu is often bad for usability and accessibility, it could also take away some of the pain related to "things not being where I expected"
    1 point
  19. I wrote up a detailed tutorial on how to use this: https://processwire.com/talk/topic/11806-tutorial-building-a-simple-rest-api-in-processwire/
    1 point
  20. Haha! I must say though, it was partially unbearable - technically in a heat wave down here.
    1 point
  21. Agreed. This is a surprisingly common gotcha for regular users. Opening the page tree again to unselect selection is not very intuitive.
    1 point
  22. I welcome 2016 roadmap but I also think that open github issues should be fixed/closed first (cleaning the desk)...
    1 point
  23. 1 point
  24. 1 point
  25. Hi guys, Been "kicking the tyres" on some UI tweaks to the PW image fields and modal windows. Many of these are in-progress designs and to be straight, none of the designs are entirely resolved. At this stage, I thought I'd throw them up (poor choice of words!) and maybe someone can take them further or offer some fresh eyes. I'm not a developer so making these a reality is impossible for me. They're flat designs. Why? PW is an amazing experience for editors. It's just so elegant and beautifully realised (especially with Reno Theme) that often, my training sessions with clients are very brief. One area which does cause friction though has always been concerned images, image fields and image modals. Especially with the latest image modules, I think a lot of inconsistency has crept into the UI. Hopefully these designs can help improve things a bit. A tiny part of the design work is influenced by a similar idea I had for MODX but which never progressed. 1A. Current Image Modal Editor has clicked 'Add image' icon in CK editor. Issues: I believe the Upload Image button can be better placed. It's not clear to users that they have a choice of two actions (Select an Image OR Upload one) To help solve this, I thought we could: Place available images under a Choose tab Create another tab titled Upload Rename modal to just Image (from Select Image) tweak slightly the Images on page path to be less prominent The following image illustrates the result. Clicking the Upload tab would result in: In the above image I've created toggle-able accordians for Drag and Drop and Manual upload. This follows closely the UI an editor is presented with when choosing Insert Link within CK Editor. IE Link to URL, Select Page and Select File and the extra Attributes tab. So overall, it's more consistent. 1B. Alternative to above - combined Select and Drag/Drop I thought it might be worth exploring what modal would look like with no tabs and a single UI for both Selecting an image and Drag/Dropping. 1C. The Image field I then moved onto looking at the Image field in PW. So currently it looks like this (below) for a simple image field called Image Gallery. So although the current Image field works great, I wondered if there was a way to simplify it by Making the drag/drop more visual and obvious Moving the Choose Files button and removing the No file chosen text and the file types allowed Here's the result. Admittedly, this treatment adds more height to the overall field. Here's how it looks when images are uploading (slightly smaller plus icon and "drag and drop..." text. To be honest, I can't recall what other changes I made there! And here's a proposed layout for when there are multiple images. This includes image titles grid layout mouse-over for edit and delete options/buttons 2. Cropping Next thing I looked at was cropping. Native cropping introduced recently is one of my clients favourite features and time-savers and I wondered if things could be improved a little. So heres the current layout (this may have changed further recently) And here's my proposal. Changes are: Width, height and X and Y fields are moved below the image Apply and Cancel placed bottom right of the image Save Crop should be titled Apply. I think that's less confusing as in some instances there are so many Save options Save and Replace should be greyed out further In addition to this, I thought it'd be neat if we had the free-form cropping function introduced by Ryan combined with some kind of list of pre-sets (displayed on right hand side). Forgive the croptions label (Crop + Options pun - I was tired!) The benfit of this I think is that Modules such as CoppableImage and native Crop would be unified in a single UI. Presets (on right) could be a few out-of-the-box presets which come natively. Croptions houses any crop ratios defined in image modules. if CopppableImage isn't installed, they just don't display.. That's it. I wish I'd more time to work on this but it's at the stage where it's ready for some initial thoughts. Hope you guys like.
    1 point
  26. Nothing better to cure The Erector Set than the PW roadmap for 2016! Everything looks so exciting, thanks for the great work! I look forward to keep developing and contributing to the community this year, it's included in my new year objetives Happy new year!!
    1 point
  27. Hi @jon9china, hhm, yes, sorry. The httpHosts array needs to be changed to (at least) include the new hostname too. (Or is set to only hold this domain name). It is for security reasons, but this isn't the reason for the 500. Regarding the 500 internal error: You need to check write permissions for folders and files under site/assets/. (Including the assets folder itself.) PW needs write access to create / delete subfolders and files. During installation you have defined chmod values for files and folders for that, it is noted in your site/config file. (e.g. 0755 and 0644, or 0777 and 0666). Check if files and folders in the subdomain are assigned that way. Also, if the 500 is gone and you can access the admin but get some errors there, you should go to -> modules -> refresh (search for new). PW uses cached informations for all modules (installed and uninstalled ones), including pathes. This needs to be recreated, too, if it isn't automatically. Please report back when all is working ok, or if there is anything other that doesn't fit. PS: here is little troubleshooting guide from Nico, regarding regular installation processes: Doesn't fit in your case, as your orig site is already running, but maybe is nice to have bookmarked for future installations on (foreign) hosts.(?)
    1 point
  28. Show off . Here It's a mild 11°C with almost 25 mph wind Happy new year!
    1 point
  29. I found this one to be the easiest to use: https://www.mamp.info/en/ You can find a lot of tutorials on the net on how to set it up. There are alternatives too, for example: https://www.apachefriends.org/hu/ Edit: and if you want to move it later on: https://processwire.com/docs/tutorials/installation-moving-and-troubleshooting/page5
    1 point
  30. Done. Renamed the module to ProcessSetupPageName and added it to the modules directory. http://modules.processwire.com/modules/process-setup-page-name/
    1 point
  31. Why not using existing methods? As @LostKobrakai said, git submodules are not used by many because of the peculiar workflow. There is a module to handle core upgrades: Core Upgrade. Or - if you're familiar with using git - you may consider using wireshell, this is a command line interface like drush for drupal. Instead of `git submodule update` just execute `wireshell upgrade`. If there are no changes the `index.php` and `.htaccess` files are updated as well.
    1 point
  32. The processwire repository is a place to keep "processwire development". So it's git repository is not meant to comply with anything other than that usecase (the site directory is even excluded). For your own projects you can create a own repository how ever you want. While submodules sound like a great idea it's not used by many, because it's workflow is far from optimal. Also, why technically moving the index.php's logic would be possible, that strategy does not work for the .htaccess file, which is also changed every now and then dependent on the processwire version. That file does need to be in the root directory to work correctly.
    1 point
  33. Since there are a lot of topics about the same theme, I decided to write a small module which overwrites the core function ___SetupPageName(). The module allows now to populate the page name using proprietary date() function. Works like PHP date() with follwing exceptions: Everything between the brackets is detected as format string, meaning no 2nd parameter possible. No need to use quotes around the format string. Spaces not allowed. from any page property, page field including subfields, parent property, parent field etc. Meaning everything what you get with $page->get(); including dot syntax. The function will give error and warnings in case of unproper settings, but creates the page with name 'untitled' anyway. Download here: http://modules.processwire.com/modules/process-setup-page-name/ Some Examples The following settings in parent template 'Name Format Children' will assign name immediately. date(Y) date('Y-m-d') parent.title parent.parent.title parent.id template.id assign name after page saving and/or population of depending field. Overwrites 'untitled' after all fields which are defined in parent template are populated. id (any other page property) pagefieldname, multiple pagefieldnames show a warning. pagefieldname (value not populated)show an error. date() // empty, no format assigned date(Y // missing closing bracket date(Y md) // unallowed space notexistingfieldname notexistingproperty existingfield.notexistingsubfield The function in the module ___SetupPageName() could be completely copied as is to the core class $pages. @Ryan Would be nice to see this in core. Related topics: https://processwire.com/talk/topic/8576-name-format-children/ https://processwire.com/talk/topic/8217-name-format-for-children-based-on-any-field-not-just-title/ https://processwire.com/talk/topic/11628-custom-page-name/ https://processwire.com/talk/topic/11349-page-add-step-not-being-skipped-when-name-format-for-children-is-set/ https://processwire.com/talk/topic/10701-automatic-page-name-using-processpageaddexecute-and-pagetable/ https://processwire.com/talk/topic/10208-pagetable-automatic-page-name-format-when-multiple-templates-allowed/ https://processwire.com/talk/topic/9979-name-format-for-children-for-multiple-allowed-templates-for-children/ https://processwire.com/api/modules/process-template/ Any recommandations after testing welcome. Download here: Download here: http://modules.processwire.com/modules/process-setup-page-name/ Edit: small enhancement to prevent display of warning twice. 23.12.15 multiple values possible now 24.12.15 made compatible with PW 3.x 27.12.15 Update Version 1.0.8 09.01.16 Update Version 1.1.0
    1 point
  34. Since you are creating a user for each author, you can simply use a page reference field for this. If a user is selected on that field, that's the one considered the author, if there is no user selected it's assumed that the author is the user that was logged when posted. $author = $page->get('author|createdUser'); //if chosen "Single page (Page) or boolean false when none selected" on the field settings Of course not all authors have to be users. You could also have a "author" template, and create all authors there. In that case you could do something like: $author = $page->author ? $page->author : $pages->get("template=author, name={$page->author->name}"); edit: none of those were tested, i just want to illustrate a concept
    1 point
×
×
  • Create New...