Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 03/12/2017 in all areas

  1. Hi, I have created a site profile that shows how to integrate ProcessWire 3.0 with Vue 2.0. See repository here. How this site profile works This ProcessWire site profile is loosely based on the REST API tutorial by @gebeer. Here are the most important steps to reproduce it: Admin settings Create an api template with default settings and just the title field assigned to it. Refer to @gebeer tutorial for further details Create a pages and nav templates with just the title field, for both template tick “Allow URL Segments” in the “URLs” tab (see attachment) Create a home template, this is going to be the single php file that will load your Vue SPA. Assign this template to the root of your website Any other template you create should have the “Alternate Template Filename” field in the “Files” tab set as home (see attachment), in this way if a user enter the website from any url that is not the root, ProcessWire will always redirect to the home template, Vue router will handle the url and call the right data through the REST API Under the root, create an api page and assign the api template to it (you can set “hidden” to this page so doesn't show up in the menu) Under the api page, create the pages nav and pages (see attachment), and assign the templates nav and pages to them. Now you have the www.sitename.com/api/pages and www.sitename.com/api/nav urls that you can use to fetch the JSON data PHP template setup In the templates folder, create home.php file and leave it empty, the HTML will be generated by webpack Now create pages.php and nav.php files. On these files is where we return the JSON data, based on the right url segment. Again, refer to @gebeer tutorial for further details on this matter. Note that I wrote a PageFields class that I use on these templates to fetch ProcessWire fields. The fields that are supported are text, textarea, repeater, img. Other fields may work but I haven't tested them. See the REST API setup for further details about how to use the PageFields class REST API setup You can decide what fields are included and what fields are excluded by passing a configuration array to the PageFields class. You can find here a list of the available configuration settings. See examples below. Show only selected core fields: $pageFields = new PageFields($p, [ 'fld_core_included' => ['url', 'httpUrl', 'template'] ]); Show no global fields, and only selected custom fields: $pageFields = new PageFields($p, [ 'fld_core_included' => [], 'fld_include_all' => false, 'fld_included' => ['title', 'gallery'], ]); On a gallery image field, hide breakpoint listing and show only httpUrl field: $pageFields = new PageFields($p, [ 'img_fld_overrides' => [ 'gallery' => [ 'fields' => ['httpUrl'], 'bp_list' => false ] ], ]); Webpack setup The most important file of all Webpack setup is config/index.js. On line 33 you need to provide your domain name so that Webpack can proxy the ProcessWire REST API to the Webpack dev server. Without this you wouldn't be able to take advandage of the Webpack hot module replacement feature which allows you to reload a vue module without refreshing the page, it also allows you to keep the state of the app. Notes My REST API may have bugs, this is just an example of an integration with ProcessWire, I suggest you either build your own REST API or use the awesome GraphQL module by @Nurguly Ashyrov. Todo Replace REST API with the GraphQL module. This requires vue-apollo, the Apollo/GraphQL integration with Vue, and vue-supply for integration with Vuex.
    7 points
  2. Dear all, I want to apologize for my harsh comment which was a spontaneous reaction and not well thought-out. I highly appreciate the spirit of this friendly community and didn't want to hurt anybody. Those of you who have read more of my posts know that usually I try to be constructive and not a troll. Best wishes ottogal
    6 points
  3. Thanks @LostKobrakai and @diogo ! Very reasonable thoughts from you both. Agree that creating a whole new logo could be too radical. But the problem with non-uniqueness still exists. Maybe we need to do some facelifting to the freshest logo included in uikit admin theme. Will think about. @diogo , thanks for the link to the very interesting thread about PW branding, didn't read it before. @LostKobrakai , special thanks for Your opinion about the main PW website. It works like a charm but is a bit outdated from the point of view of visual representation. Can try to draw some sketches on the subject if there will be some interest from the community. Anyway we need to discuss all that because PW is an amazingly powerful and simple tool which truely deserves to be widely known and to have a better brand than now.
    3 points
  4. @ottogal Independently of the opportunity of this suggestion, It doesn't sound at all like @theoretic is joking, you can see that there is some thought and work in that logo either you like it or not. There's too much trolling going around the world these days, let's try to keep this little corner of ours a nice and constructive place. I'm not trying to bash you down, but please try to be a bit more explicit about what you didn't like when criticizing someone else's post. @theoretic you might want to go through this thread to get a feeling of what was already discussed about this subject
    3 points
  5. Hi all, My first – hopefully useful – ProcessWire related tutorial: http://szabesz.hu/blog/install-processwire-in-a-subfolder-on-shared-hosting-cpanel_ins-sub/
    3 points
  6. Page Image Manipulator allows you to watermark image variations, which is more flexible than watermarking the original on upload. If you are concerned about sneaky visitors gaining access to the unwatermarked originals see @horst's solution here:
    3 points
  7. New feature in v131: new move to first/last buttons for file/image fields (FileFieldTweaks). This adds up/down icons (right-left in case of images) that you can use to move items to the first or last position.
    2 points
  8. This should help you get rid of the 'annoyance'...
    2 points
  9. That is what happens in the backend (you're logging in to the admin), but you can create your own frontend login procedure as well (completely from scratch or with the FrontendUser module). In that case, you control where the user gets redirected to.
    2 points
  10. WireMail is there to send mails and not to care about what it's sending or how that markup is created. You can create the html markup, which should be sent, in whichever way you desire. It could be a page being rendered, there's wirePopulateStringTags() or you could stitch together strings in php. That doesn't sound right.
    2 points
  11. First of all, so the whole post doesn't sound overly harsh and negative: It's great to see that you want to help out and change something, but the way you took might not have been the best one. So now we have four of them. The problem the project does have in terms of corporate identity is not the lack of a good logo (our latest one present in the uikit theme is actually quite nice), but rather that it's hard to get things changed to one consistent look if there isn't one driving force behind that change with all the needed access. E.g. even just the processwire website has naturally grown to consist of about 4-5 destinct parts, which would need to be updated. And there's not only the logo, but the whole site could sport a freshed up look. It would clearly be nice to have those changes be done more quickly, but to be honest it's only Ryan who could lead the whole process to an end and he has a lot more than just this topic on his todo list. There's certainly willingness in the community to help out, but too many cooks spoil the broth and it'll still need Ryan to be involved in the process to at least lead the whole effort.
    2 points
  12. 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
    1 point
  13. Hello I made a simple app for reading the main RSS for ProcessWire news. Now you can access ProcessWire Blog, ProcessWire weekly and the Latest Forum Posts in a Single App in your iOS or Android smartphone. Open Source of Course. Made using the http://jasonette.com technology. You can compile your own app if you want. For A Quick Look 1.- Download the Jason App (iOS) https://itunes.apple.com/us/app/jason./id1095557868?mt=8 (Android) https://play.google.com/store/apps/details?id=com.jasonette.jason 2.- Use the Following Url https://raw.githubusercontent.com/NinjasCL/pw-app/master/app.json Source Here https://github.com/NinjasCL/pw-app
    1 point
  14. Hello. Just wanted to ask if there if there is a way to NOT delete Repeater (or Matrix) Items directly but move them to the Standard Trash if the Trash-Icon on the Edit Screen is clicked? This would be helpful when editors accidently delete some Repeater-Items. There is also no Confirm Message when deleting. Especially in Repeater matrix Items there can be a whole lotta Content wich is gone forever. Thanks for every Info...
    1 point
  15. @Ivan Gretsky ooops....I am a beginner PW user I didn't even know it was possible to do that! I'll check it out when I have the time, thanks
    1 point
  16. Cool stuff, @microcipcip! Please do write a tutorial when you have time. I am sure it will be useful to many of us in the community. Surely it will be for me . It seems like your boilerplate is not in a site profile format. Is there a reason for that? If not, consider using it, as it is a common way to distribute site boilerplate code and could make your work easier to reuse for PW people.
    1 point
  17. Whatever field settings I used - with/without HTML Entity Encoder, CKEDitor/Textarea, txt/markup - I kept getting '&lt;p&gt;' or '<p>' in my emails. I finally got it working by using no Text Formatters + CKEditor + Markup and then put strip_tags() around the field in the template. Not sure what that means and I may have missed a correct way to do it. I ran out of time/patience. This works for now.
    1 point
  18. I'd really rather suspect that then WireMail not sending newlines. Still could be a bug in one of the 3.0 additions to wiremail.
    1 point
  19. If you want to get involved I'd suggest you to add your thought to the mentioned PW branding thread. It's basically our most current state of branding and evolving from there would probably be the best.
    1 point
  20. If anything it appears that SessionHandlerDB makes it worse, at least based on my limited testing.
    1 point
  21. Awesome @Robin S - thanks for the testing. If I gather correctly, it seems like that column type change has fixed everything which is great. Yes, you are right, Tracy stores the html for all the panels in the session and it can get quite large, especially with all the field object info I have in the PW Info panel. Glad this was an easy fix in the end
    1 point
  22. Changing the data column type did fix the issue - thanks! I guess that issue occurs because Tracy is storing a lot of data in the session. Before changing the column type I did some logging of static::$showPanels - much of the time it would be an array but randomly sometimes null. No more nulls after changing the column type.
    1 point
  23. right - yeah, i'm not actually using the module, just the function which is in my generic site utilities module; using this replacer method (as opposed to hardcode) though allows you to have a few frequently used replacements in a lot of fields, e.g: page.id page.httpUrl etc..
    1 point
  24. Thanks for the extra info. I have been working to eliminate all the SessionHandlerDB issues - it's been a total PITA. As far as I can tell in PW 3.x the only remaining issue is that the redirect debug bar doesn't show. The normal and AJAX ones work. I haven't tested thoroughly with 2.7 in quite a while. I have been PM'ing with Ryan regarding the redirect bar and it turns out that I do have a solution by modifying Session::redirect (https://github.com/processwire/processwire/blob/35df716082b779de0e53a3fcf7996403c49c9f8a/wire/core/Session.php#L926-L959) to move the header() call to the top of function. Ryan said it used to be that way, but some servers had some issues. I suggested it might be due to the server's "ignore_user_abort" setting, but I am waiting to hear his thoughts on that. Sorry, that was probably more detail than you wanted. The upshot though is that I am wondering if that change to Session::redirect might also fix the issue you are having. The other possibility might be this line (https://github.com/adrianbj/TracyDebugger/blob/b3750ee32fd7e5cdf14dc9e58a18ec2ffaab0b01/TracyDebugger.module#L1105) - does removing that help? It's there for other SessionHandlerDB issues, but it can be removed if Session::redirect is modified as mentioned. Back to the differences between Master (2.4) and Legacy (2.3) of the Tracy core - the primary advantage to Master is the addition of the AJAX bar. You'll actually find the rendering of the debug bar in the Legacy version much faster - I have an issue (https://github.com/nette/tracy/issues/247) posted about this, but not sure much can be done to fix given the way the master version works. Not sure if that helps or if you feel like investigating any of those tweaks. I don't want to put much more effort into this until I hear back from Ryan because I am already beyond frustrated with the issues with the SessionHandlerDB module, and from what I can tell it is currently pretty good with PW 3.x. Cheers, Adrian
    1 point
  25. Hi @Robin S - just to clarify - the only "form" this happens on is saving the Tracy settings page? Are you running the latest version of Tracy? Do you have the SessionHandlerDB module installed? If so, does it make a difference if you uninstall it?
    1 point
  26. Thanks, but unfortunately there were other issues with the current approach. In v130 (just uploaded) all should be fine, and pagelist IDs are visible in the new Tree menu too. This version also contains the option to align the top nav to the left in the default admin theme (idea & request by @Robin S - thanks!).
    1 point
  27. I thought of a concept and it doesn't have to be as complex infact here's my proposition There should be a changelog.md and also another changelog.json which contains each version and the text serving as the changes, however this might hard to implement as it means enforcing everyone to do this, another better alternative could be a changelog.md with a specific format to follow, so that a Parser can be read to extract the needed information, it is vital a changelog is seen before uploading to inform user about what has changed and what to expect.
    1 point
  28. 1 point
  29. @Robin S thanks for the advice. I design sites from scratch with my own small sass boilerplate for typography etc, including the awesome @include-media for breakpoints, best solution I've seen. My CSS skills outweigh my JS ones but I'm working hard on JS at the moment to catch up a bit (although the syntax bothers me somewhat). My charity work is the mental health/learning disabilities sector and it is a field I'd like to stay close to. I feel they make an actual difference to people, rather than the 'design studio look at our new ad for pepsi' stuff. Worth millions but all it's good for is giving people bad teeth. My PHP skills are ok (as long as I have the manual close...) but this is why I like the PW API so much, grabbing stuff out the database just couldn't be simpler. Anyway, I'm rambling. I just love making websites basically! Have done for over a decade, it never gets old for me, my enthusiasm probably outweighs all my skills combined
    1 point
  30. Hi @antpre and everyone. I lack time in recent days but the module should be available to the public the next coming week!
    1 point
  31. You might want to add hour/minute(/seconds) definitions as well or you might miss some edge cases in comparing those timestamps. It's not only comparing the date part.
    1 point
  32. Do you do design websites as well as develop them? If you do then my experience has been that there is plenty of work available from businesses and organisations who care about and understand the benefits of high-quality bespoke design and development. Yes, there are many out there who think that a $40 Wordpress theme is good enough and don't want to pay above the minimum - if job satisfaction is important to you, you don't want those people as clients. You'll hate the client, hate the finished website, and end up hating your job. You say you also work in the charity sector - I think that is a good sector to target as a specialisation and maybe you can make use of your contacts there to get started. Most of my clients are not-for-profits, mainly environmental organisations. I have found them to be excellent organisations to work with - friendly, sensible people, happy to take advice and willing to let you get on and do your work without a lot of interference. Another benefit is that these organisations often fund their projects from grants. This makes them less price-sensitive. To be clear, I'm not talking about gouging them on price - just that you can quote a fair price and they base their funding application on that and there's no grizzling and bargaining over cost like you can get in the for-profit sector. I live/work in the middle-of-nowhere rural New Zealand, I have never advertised or done any kind of promotion, and have been fortunate enough to always have a steady stream of work. And believe it or not, in the ten years I have been doing web work I have never had a client request a Wordpress site. I think positive word-of-mouth is key, and the great thing about it is that good people tend to know other good people so you generally avoid those Clients From Hell. To get good word of mouth you need to exceed expectations - set yourself high standards, have meticulous attention to detail, and deliver that bit extra. Best of luck with your career!
    1 point
  33. Not an answer to your question sorry and only useful for those with Lister Pro, but just wanted to note that you can export the filtered list of users with "Export Pages to CSV" action for Lister Pro.
    1 point
  34. His pearls of wisdom were an attempt to help you and others who may come across a similar situation. I'm out!
    1 point
  35. You can also use timestamps in a PageFinder selector or anything that works with strtotime(): $zaehler = $page->children("einsatzdatum>=first day of January 2017, einsatzdatum<=last day of December 2017");
    1 point
  36. I thought I would just pop by to say how much fun I am having. I don't really get the chance to put websites together at the moment for some complicated reasons, but I have put some days aside to nail together a new blog about something. And I have thoroughly enjoyed it. Especially all the little tweaks I have been making. For instance, I want the layout on the front page to be very neat, but that means the titles of articles have to be a certain length, as do the summaries and the images, where they are available. That particular constriction doesn't necessarily work in other areas of the site. With PW, the answer is dead simple. TWO title fields, both with the counter switched on and a little note reminding me of the ideal length. I also have two summary fields for the same reason. I have a similar thing with images. I have made up a Photoshop template with Artboards for all my various image sizes - featured image, summary image for the front page, story images for the article, sidebar images and the SEO image. Of course, the fact that I can have an assortment of images in my PW template means I can take advantage of this PS template. And, because some articles just don't have an image, I have a little note telling me to write a longer summary if there is no image. Oh, and a bit of PHP that looks for the short title and uses the long one if I forgot to write a short one ... and so on. I know this is all mundane stuff compared to some of the cleverer functionality Ryan and the various mod devs are coming up with, but for me, it is this simpler versatility that makes Processwire so powerful. That I can just shove in another field to get around a certain problem and bring it up as an alternative with one line of PHP makes sites a joy to develop. Enough so that I actually spent a happy hour today neatening up my code, indenting it nicely and putting helpful little comments everywhere. I didn't need to do it, but I have worked so much faster than I could have with any other system, I had the time - so I had my little bit of fun.
    1 point
  37. This is a shorthand function. So its easier to populate tags. /** * Perform a language translation replacing string tags. * * Used as an alternative to sprintf in language string that requires variables. * uses wirePopulateStringTags function for replacing tags. * * The $vars may also be an object, in which case values will be pulled as properties of the object. * * By default, tags are specified in the format: {first_name} where first_name is the name of the * variable to pull from $vars, '{' is the opening tag character, and '}' is the closing tag char. * * The tag parser can also handle subfields and OR tags, if $vars is an object that supports that. * For instance {products.title} is a subfield, and {first_name|title|name} is an OR tag. * * @param string $text Text for translation. * @param WireData|object|array $vars Object or associative array to pull replacement values from. * @param string $context Name of context * @param string $textdomain Textdomain for the text, may be class name, filename, or something made up by you. If omitted, a debug backtrace will attempt to determine automatically. * @param array $options Array of optional changes to default behavior, including: * - tagOpen: The required opening tag character(s), default is '{' * - tagClose: The optional closing tag character(s), default is '}' * - recursive: If replacement value contains tags, populate those too? Default=false. * - removeNullTags: If a tag resolves to a NULL, remove it? If false, tag will remain. Default=true. * - entityEncode: Entity encode the values pulled from $vars? Default=false. * - entityDecode: Entity decode the values pulled from $vars? Default=false. * @return string Translated text or original text if translation not available. * */ function _st($text, $vars, $context = null, $textdomain = null, array $options = array()) { return wirePopulateStringTags(__($text, $textdomain, $context), $vars, $options); } echo _st('There are {count} {items} in the {place}', ['count' => 5, 'items' => 'oranges', 'place' => 'tree']);
    1 point
  38. I guys, fresh new website to showcase https://iloetscher.com/ iLötscher is a Swiss company based in Zürich that provides informatics services for Apple devices and networks. We are still working on the English version and the private area. ProcessWire wise, the website is quite simple and the only non-core modules used are the Pro-fields Table and Hanna Code — both, together with Repeaters, to support the creation of the price tables: SSL is provided by the free Let's Encrypt, that I heard from in this forum (Thanks guys!). The hosting didn't support it (and I didn't have Shell access) but they were happy to install the Let's Encrypt extension for Plesk. Just wanted to let you know that it is worth insisting a bit, in case you encounter the same problem. For the time slot reservations we are using Calendly. It works quite well, and the options for embedding the system on the wesite are very flexible also. The site is responsive, of course. Feedback is more than welcome, thanks!
    1 point
  39. Here is something I hacked together quickly for automatically adding new child pages to the pagetable field. This is only if you are using the page as the parent. It also handles deletion of items if they are trashed externally. I also disabled the internal check for orphans - because they have been automatically added already, there is no need for the "Children were found that may be added to this table. Check the box next to any you would like to add." option. I seems to be working great here, but please test carefully!! Add this to your admin.php file: wire()->addHookBefore('InputfieldPageTable::render', function($event) { $pp = wire('pages')->get(wire('input')->get->id); $ptf = $event->object; //remove pages from pagetable field if they were externally trashed foreach($pp->{$ptf->name} as $item) { if($item->is(Page::statusTrash)) $pp->{$ptf->name}->remove($item); } //add pages to pagetable field if they were created externally foreach($pp->children as $child) { if(!$ptf->has($child->id)) { $pp->{$ptf->name}->add($child); $pp->of(false); $pp->save($ptf->name); } } //reset orphans property so that we don't get a message asking to add new pages that are now already automatically added $ptf->setOrphans(new pageArray()); });
    1 point
  40. Both guys here are correct. The session needs to be regenerated with a new session ID and some new cookies need to be set, etc. Redirecting after successful login ensures you are dealing with the new and authenticated session and $user, ready to work with.
    1 point
  41. You could accomplish the above in various ways. I'll cover two: Option 1: Structure -people --john ---organization 1, ceo, 2010-2012 ---organization 2, board member, 2009-current --mike --etc. The above would have child pages of each person that represents their organization connections. The fields on that template would be: organization (single page select to /organizations/) position or title (text, their position at the organization) start_year (integer) end_year (integer) Option 2: Repeater This is the option I would use, and it's perfect for this sort of thing. It's basically doing the same thing as option 1, but making it simpler and disconnecting it from the structure. You'd create a new field using ProcessWire's repeater fieldtype, perhaps naming it 'organizations' or 'person_organizations'. Then add the same fields mentioned in the bulleted list above. Add this new 'person_organizations' field to your 'person' template. Now you can define as much meta information for that person<->organization relationship as you want to. More on how to use ProcessWire's Repeater fieldtype
    1 point
  42. you can use the pagetype field for all these relations. It's just a mater of organizing your pages accordingly. So, taking your example, you could organize your PW tree like this: -people --john --doe --xico --... -organizations --acme --corporation --lda --... -industries --candies --guns --moon trips --... -types of people --nice --bad --so so --... Then, on the template for organizations you put a page field with "industries" as parent of the selectable pages (PSP), and on the template for people you put two page fields, one with "types of people" as the PSP, and the other with organization as the PSP. You can make this system grow indefinitely Just think that any time you want a dropdown, or a selector for multiple choices in your templates, this is the way to do it in PW, even if those pages only exist to be a selectable value on other pages. Edit: And welcome to the forum
    1 point
×
×
  • Create New...