DrQuincy
Members-
Posts
287 -
Joined
-
Last visited
-
Days Won
1
Everything posted by DrQuincy
-
Thanks a lot for such a detailed reply, it is most useful. ? I always leave the login as /processwire but then they tend to be brochureware type sites so not exactly highly sensitive. Yes, I think this is exactly what I will do. Like you say, it's easy to do so might as well.
-
To keep the main site tree clean I have added a collection of JSON templates to /processwire/api/{reference} However, it has occurred to me that this means I need to include that path in my JavaScript to make the API call. Am I at any significant disadvantage if a hacker knows the CMS login path to be /processwire/? I know WP users change /wp-admin/ to something else but it is my understanding ProcessWire is much more secure. Does it really matter? The docs say there is dictionary attack protection built in via throttling. Thanks.
-
I have this code: $formPage = wire('pages')->get('/forms/contact/'); $formPage->of(false); $formPage->formFields->get('id=1075')->formFieldLabel = '<strong>Test</strong>'; // This works $formPage->formFields->get('id=1075')->formFieldAttributes->get('property=placeholder')->value = 'New placeholder'; // This does work echo $formPage->formFields->get('id=1075')->formFieldAttributes->get('property=placeholder')->value; // Echos old value rather than 'New placeholder' I have forms stored in a template. I want to be able to dynamically override some of the values in the page/ form file but I don't wish to save them. The reason being I pass the \ProcessWire\Page (form) object to a function that creates the HTML for the form. Saving it would alter the form in the database whereas I just want to do it for this request only. In this case formFields is a repeater and formFieldAttributes in a Pro Fields Table field. Is this possible?
-
I just wanted to check how the new “Prevent direct access to file assets owned by pages using this template?” option works under the template Access tab. The first option works as PW has done historically. If I choose the third option then it seems I only get a 404 if the current user doesn't have view access to the page. So, that's great. It seems to change the folder now so that is satisfies a different .htaccess rule to control access. What I'm unsure of is in the second option where it says: What is meant by “publicly accessible”? Would this be a page that uses the admin template? I just wanted to understand how it works because to me this implies role access — which seems to be the job of the third option. To be honest, if I ever wanted to secure files in this way I think I'd use the third option anyway. One general question: if you chose the third option and wanted to log the number of times a restricted file is accessed, which hook would you use? Thanks.
-
Thanks for confirming. Another problem solved on this great forum. ?
-
Thanks. I have found out the issue and it was not permission-related. In file-errors.txt I had this error: allowPath: pathname may not traverse “../” I don't really understand how it works but from looking at the source is seems WireFileTools->allowPath() is blocking it. This fixes the error: public static function createDuplicateImage($src, $dest) { if (file_exists($src) === false) { return false; } // Duplicate the file \ProcessWire\wire('files')->copy($src, $dest); // NOTE new line $dest = realpath($dest); return new \ProcessWire\ImageSizer($dest); } You need to call realpath() after file duplication (since realpath() does not work on non-existent files). This sends the full canonicalised absolute pathname and WireFileTools via ImageSizer deletes the -tmp files. I'm not sure if this is intended behaviour but I hope that helps anyone else who needs to do this. I presume it is a security feature that blocks certain paths from file manipulation.
-
@horst Thanks, this works great but I am left with some -tmp images. What I needed to do was create thumbnail images outside of PageImage context. So I need to duplicate the file first and then pass it to a new ImageSizer object and resize per your example. My code is like this: public static function createDuplicateImage($src, $dest) { if (file_exists($src) === false) { return false; } // Duplicate the file \ProcessWire\wire('files')->copy($src, $dest); return new \ProcessWire\ImageSizer($dest); } // ... $image = Util::createDuplicateImage('./foo.png', './foo-cropped.png'); $image->resize(250, 250); I get foo-cropped.png sized to 250px x 250px but am left with a duplicate foo-cropped.png-tmp.png. Looking at the ImageSizeEngine class this line is returning false for some reason: $this->wire('files')->unlink($this->tmpFile); Any ideas why? I am just on a local MAMP set up and have never had problems creating and deleting files with PHP before. Thanks. ?
-
Ah, thanks. The documentation is great but with some many features it's easy to miss things. Here's the relevant page from the docs should anyone need it: https://processwire.com/api/ref/image-sizer/ Thanks to you both. ?
-
If you want to resize an image that is not a PageImage is there a way to do it? No worries if not as I can just get Intervention Image via composer but didn't want to include a library I didn't need if PW can do it. I can't see anything in $files and it seems functions like size() can only be applied to PageImages. Thanks.
-
It seems this is part of the ProcessWire core now so if you install 3.0.184 there is a template option: If you look in the latest PW there is a new rule that blocks access to folders in site/assets that start with a hyphen. If you attempt to access the corresponding URL without the hyphen PW will do authentication checks. Direct access to the folder throws a Forbidden error. If access is blocked to the file it 404s irrespective of the What to do when user attempts to view a page and has no access? setting. See
-
How to send specific HTTP status code and go to error page
DrQuincy replied to DrQuincy's topic in Getting Started
Not sure if this is the best way as it involves adding code to every template file but this seems to work. Add a function in functions.php such as killWithstatusCode() that returns a simple HTML error template. This can check the current HTTP response code and output a message accordingly. Then at the top of each template add: if (http_response_code() != 200) return killWithstatusCode(); Technically, the response code could be between 200 and 299 and be regarded as a success so you could replace http_response_code() with a more concise function that checks if the code starts with a 2. if (!statusCodeSuccess()) return killWithstatusCode(); I did see Ryan say in an old forum post that if you don't wish to render a template then you can simply call return and ProcessWire will still handle the process. I also noticed that whatever string you return from the template ProcessWire will render. You might wonder the use case for this. I find it useful to be able to allow a CMS to use HTTP response codes that typically the server would handle. Being able to send 405 Method Not Allowed, for example, when creating a RESTful API or handling POST forms can be useful. Or if you wish to block POST requests to a certain page. Also, 400, 401, 403 and 500 are useful codes when building web apps. I have adapted ProcessWire to use a MVP pattern so this means I can send out a non-2XX status code before the view (template) is rendered and not have to worry about that part. Unlike a 404, these errors are generally unlikely to be encountered under normal usage are are more indicative of server or application error and so it doesn't matter that the full blown ProcessWire error page is not shown. If there's a better way I'm all ears. ? -
Great work, thanks!
-
P.S. One “gotcha” that caught me out was the items did not appear in the mobile nav until I logged in and out again. ?
-
Just installed this and it is really good! Thanks @Robin S, I am abandoning my Process class from the other thread. ? One suggestion. Can you dynamically set permissions? If so, it might be nice to restrict the appearance of the menus to a permission. It doesn't really matter for my use case but thought it might be worth adding if it's easy enough.
-
How to send specific HTTP status code and go to error page
DrQuincy replied to DrQuincy's topic in Getting Started
Thanks, I wasn't aware of the $http variable. ? Looking through the functions I think possibly this is more suitable in this instance. https://processwire.com/api/ref/wire-http/send-status-header/ I'm sure HEAD work work — though I may be wrong! What I am wanting to do is send something other than a 200 status for the current request. It looks like $http->sendStatusHeader(405) would send the right header per my above exmaple. Is it possible to then show the error page template? -
Ooh, this looks great! Thanks Robin. I'm still on .165 at the moment so will have to upgrade. ? Out of interest is there a technical reason why it's limited to three menus? Also, do you think there will ever be support for the navJSON type links? I.e. Main > drop down item > third-level item.
-
How to add drop down menu in the backend with icons
DrQuincy replied to DrQuincy's topic in General Support
Thanks for clearing that up. I've pretty much got it doing what I want no anyway! I don't really need links to other hosts, etc. I just wondered if it was possible should the need arise. -
How to add drop down menu in the backend with icons
DrQuincy replied to DrQuincy's topic in General Support
Bear in mind each time you make a change to your .module file you need to refresh modules. Here's a working sample that should get you started. namespace ProcessWire; class ProcessSiteOptions extends Process { private $cmsPath = null; public static function getModuleInfo() { return [ 'title' => __('Site options', __FILE__), 'summary' => __('Custom site options', __FILE__), 'version' => '0.0.1', 'permanent' => false, 'useNavJSON' => true, 'permission' => 'page-edit', 'nav' => [ [ // URls relative to where this admin page is added 'url' => '../page/edit/?id=1023', 'label' => 'Settings', // These labels are HTML entity encoded 'icon' => 'cog' ], [ 'url' => '../page/edit/?id=6601#ProcessPageEditChildren', 'label' => 'Project filters', 'icon' => 'filter', 'navJSON' => 'navJSON' ] ] ]; } public function ___execute() { return $this->render(); } protected function render() { $html = '<p>Manage site options.</p><ul>'; $sanitizer = wire('sanitizer'); $nav = self::getModuleInfo()['nav']; foreach ($nav as $item) { $html .= '<li><a href="' . $sanitizer->entities($item['url']) . '">' . $sanitizer->entities($item['label']) . '</a></li>'; } return $html . '</ul>'; } public function ___executeNavJSON($options = []) { $options = []; $options['list'] = []; // Unlike nav children above these can be dynamic $options['list'] = self::getChildArray(); return json_encode($options); } private function getCMSPath() { // Caches the CMS path return $this->cmsPath === null ? wire('pages')->get(2)->path : $this->cmsPath; } private function getChildArray() { $page = wire('pages')->get('/'); $sanitizer = wire('sanitizer'); return [ ['url' => $this->getCMSPath() . 'foo-bar', 'label' => 'Arbitrary CMS link', 'icon' => 'smile-o'], ['url' => '/about/', 'label' => 'Arbitrary site link', 'icon' => 'user-o'], ['url' => $page->path, 'label' => $sanitizer->entities($page->title), 'icon' => 'home'] // Dynamic; these labels are not HTML entity encoded ]; } A few points: Don't put any comments before the namespace declaration as PW can't pick up on the module info properly As @Robin S pointed out the first level of items are static, the rest (navJSON) can be dynamic Questions (just me being picky/trying to understand): I don't know how you add third-level items, i.e. children on navJSON but I probably don't need these anyway The labels on navJSON aren't HTML encoded but the labels on 'nav' are — why is this? Is it so you can add HTML into the dynamic options? (strong, em) — just wondering why they are different How can you make a link in 'nav' not do anything when clicked — i.e. just act as a parent for the child links (not a big deal, just curious) How can you add a link (in either 'nav' or navJSON) that goes to an external site? I.e. to a different HTTP host -
I know you can throw a 404 easily enough: throw new \ProcessWire\Wire404Exception(); However, is there an easy way to throw other HTTP status codes that sends the appropriate HTTP header and loads the error page rather than the current template? For example, I have some pages where I want to restrict the request method to GET or POST only and therefore want to sent a 405 Method Not Allowed if the wrong method is requested. I don't just want to manually send the headers and exit() though — I want the error page to show and for ProcessWire to finish the request. Is this easy to do? I looked but couldn't find anything. Thanks.
-
How to add drop down menu in the backend with icons
DrQuincy replied to DrQuincy's topic in General Support
I did a very quick text and it seems to work! ? I just created a new Process class based off one that was already in there and placed it in site/modules and added the nav, stripped back what I thought I didn't need and installed the module and it pretty much worked first time. It will take a bit of tweaking but the bit I was struggling with now works. Thanks again! -
How to add drop down menu in the backend with icons
DrQuincy replied to DrQuincy's topic in General Support
Thanks for the detailed response! ? I did think it was going to require an admin Process when looking at existing pages. From the looks of it then I could create my own Process class and add the nav there. My knowledge of PW isn't wide enough to know much about how this works but it looks like I should be able to figure it out based off the example you linked to. In this case it is fine to have it hard-coded in getModuleInfo(). It is just for some specific site options such as Settings, Config, Emails that are in the site tree. I just thought it'd be nice to have it in the top nav so it appears separate from everything else. Thanks also for the #ProcessPageEditChildren tip. Just one more question please: is it any easier to to add items to existing menus? For example, could I add some extra options to the Setup menu or does this require custom Process classes as well? -
I thought this would be really easy but can't figure it out. In the backend at the top you have Setup, Modules, etc that have drop downs with icons. You can see that these correspond to pages that use the admin template when looking under Admin in the site tree. What I want to do is add an entirely new menu with drop downs and icons that look exactly the same as this. I have a redirect template that I will use to send them to specific pages within the CMS — or even the front end. Can someone point me in the right direction for how to do this (if it is possible)? Including, if possible, setting menu icons. When I add the pages in the site tree the child pages don't show as a drop down. When you link to a CMS page is it possible to use a GET var in the URL to have the Children tab open instead of Content? In my drop down I want to link to sections that show all child pages. I hope that makes sense. Many thanks.
-
I finally got round to try the language tools and they are great, as expected. I have a few basic questions please. Sorry there are a few here but I thought it better to do it in one thread. I have searched for the answers but couldn't find anything. How do you access a language-alternative field if the language has a dash in it? E.g. you can have language foo-bar but not $page->body_foo-bar; the field is not allowed (tried it without the dash and with an underscore when using the API to no avail) Is it possible to have the languages expanded by default? I.e. as though you have clicked the folder icon Is it possible to show the languages in a dropdown instead of tab for large numbers of languages? Just curious really. It's not often this would be used but I do have one site with 15+ languages that I may eventually port over. In Languages what are Live Search, Site Translation Files and Core Translation Files for? Is this irrelevant to the front end? It looks like it is for translating PHP files but just wanted to make sure it wasn't something I could make use of. I will only ever require English back-end and would store or translations in fields in the database. If you choose a non-default language in your profile in the back-end is there any way to know from the site tree that for a given page the name is not active? It doesn't appear so but I feel this is quite an important feature if managing lots of pages and languages. What is the rationale behind always searching the current language and the default language when using the API? There is a workaround here but just wondered as I wouldn't thought it better to only search the current language. Finally, let's say you have a latest news section on a site with five languages and you only wish to publish an article in one or two of those languages. Is that possible? From what I can gather so long as you are publishing in the default language you can simply uncheck the “Active” box for the languages you don't wish to have a page for. However, it looks like you must have the default one. I presume this is so it has all the fallbacks it needs. I guess it would be easy enough to throw a 404 for the default page. Thanks!
-
I have implemented this today and it seems to work well. I am storing the files in a protected folder and when I copy them there I am assigning a unique 64-bit token which is referenced via a repeater. This saves me having to manage files with the same name with a numerical post-fix. On the front-end I have a single secure-files template that uses URL segments to access the files. E.g. /secure-files/68af96520c980c0a/test.jpg and /secure-files/68af96520c980c0a/test.jpg?dl=1 to download. (reads from /my-private-folder/68af96520c980c0a.jpg) The only downsides are: If you upload a file and don't save it is technically in the public root (as mentioned above) and not deleted until the current page is accessed again You can’t view the files directly from the CMS as you can with standard Files/Images fields. Is there any field type that easily allows some arbitrary HTML based on current page field values so I could add links in?
-
I can see there is a plugin that allows for you to store files outside the document root but it seems to be a while since it was updated and some users are reporting issues. I thought of a relatively simple way of doing this and wondered if anyone thought this approach was good — or if there was a better way. I am thinking I have a Files field and then a proxy field (probably a Repeater) that stores the file path, file name, description, etc. When a page is saved the files from the files Field are copied outside the document root and the data is added as new Repeater items. The Files field is then cleared. When proxy Repeater items are deleted the files are also deleted off the server. The user could also edit any additional fields on the repeater (i.e. meta data for the file); the path field though would not be editable. Then on the front end I can access then via their repeater ID. E.g. /secure-files/1067/ Or maybe even have a name of the file as a URL segment: /secure-files/1067/document.pdf (if that is possible). Would that work — or is there a simpler way? One thing that I wondered about is if you upload a file and then don't save the page. What seems to happen is the system purges it but only when you edit that page again. This is not a big deal for this particular use case but thinking about sites that may be dealing in documents with personal information on I am wondering if there is any bulletproof method of ensuring there are never any sensitive files left in the public folder. Thanks! ?