Jump to content

DrQuincy

Members
  • Posts

    248
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by DrQuincy

  1. That's a much better idea, thanks @Robin S ?

    I have nearly got it working. My only issue is in the ProcessPageEdit::buildForm hook, how do I get the current page so I can match to my selector?

    I.e. how do I get to $page from here:

    \Processwire\wire('pages')->addHookAfter('ProcessPageEdit::buildForm', function(\Processwire\HookEvent $event) use($selector)  {
    			
    	$form = $event->arguments(0);
    
    	// ...

    $form is of type ProcessWire\InputfieldForm. How can I get to the $page being edited from that?

    Once I get this I can post the full working code.

    Thanks.

    • Like 1
  2. I have the following hook but it doesn't quite work. The idea is I can specify a selector and it prevents the client from moving matched pages and changing their name and template. I know there are already options that allow you to do some of this but I wanted to cover it in a single hook. It so the client doesn't break things by mistake and by fixing the name and location of something like /settings/ it means I can do $pages->get('/settings/') instead of $pages->get(1063).

    So I'd set the hook like this:

    Hooks::freezePages('template=settings|site-map|emails|contact|downloads');

    And then my function looks like this:

    	public static function freezePages($selector) {
    		
    		\Processwire\wire()->addHookAfter('Pages::saveReady, ProcessPageSort::execute', function(\Processwire\HookEvent $event) use($selector) {
    			
    			$page = $event->arguments(0);
    			
    			// When sorting pages this can be null so do nothing in that case
    			if ($page === null) {
    				
    				return;
    				
    			}
    			
    			// $page->created !== - filters out new pages as when you create them; only do this on pages alrady created
    			if ($page->created !== 0) {
    				
    				$page->of(false);
    				
    				if ($page->matches($selector) === true) {
    					
    					// Get previous values (see https://processwire.com/talk/topic/24216-how-to-get-old-page-values-in-a-processwire-page-save-hook-and-some-other-notes-on-save-hooks/)
    					$clone = clone($page);
    					\Processwire\wire('pages')->uncache($clone);
    					$origPage = \Processwire\wire('pages')->get($clone->id);
    					
    					// Debugging to see how any times it's called
    					\Processwire\wire('session')->warning($origPage->template . ', ' . $page->template);
    					
    					if ($origPage->name != $page->name || $origPage->template != $page->template) {
    						
    						\Processwire\wire('session')->warning('**' . $origPage->path. '** is frozen and cannot have its name or template changed', \Processwire\Notice::allowMarkdown);
    						
    						$page->name 		= $origPage->name;
    						$page->template		= $origPage->template;
    						
    					}
    
    					// Handles drag-and-drop
    					if ($origPage->path != $page->path) {
    						
    						throw new \Processwire\WireException($page->path . ' is frozen and cannot change its path');
    						
    					}
    					
    				}
    				
    			}
    			
    		});
    		
    	}

    It kind of works. It works when dragging and dropping in the page tree and it seems to prevent name changes. It only seems to be problematic when changing the template.

    If you remove all template references above (i.e. just check the name) it works fine. When you use the code as above and change the template it only seems to work if you change it to a template not matched by the original selector. It's almost like if you do anything with the template it gets called twice and on the second call the templates are the same. I know this because if you look at the debugging line it adds two warnings to the session if you change the template to something not in the original selector.

    Can any of you expert PWers spot an elementary mistake in my code? Is there something special I need to do if changing the template?

    I hope that makes sense — do ask if you need more context or information. I've been staring at it for ages and it's driving me mad!

    Thanks.

  3. If you have a Files field in the same template as a Textarea CKEditor field when you insert a link you can link to any of the files uploaded to the aforementioned files field. The same goes for Images fields and inserting images.

    Is there a way to have a central Files field as part of say a document-storage template and have all files uploaded here available to all Textarea CKEditor fields regardless of what template they are on?

    In searching for an answer I found Media Manager, which looks interesting. But I wondered if there was a way within the Processwire core to do this. I know I could make each file a page and that could be selected from CKEditor and then I do something in my code to read the file but was more interested in linking directly to the file in this instance.

    Thanks.

  4. Thanks, that's great.

    I think LoginRegisterPro does what ProcessForgotPassword does (and more).

    The "Email New User" module looks very interesting, thanks — and just what I was after.

    If any users of LoginRegisterPro are able to let me know if LoginRegisterPro offers the "Email New User" I'd be interested in knowing but good to know this module is available if not.

  5. Hi,

    A couple of questions on LoginRegisterPro that I couldn't see in the main page.

    1. Can you disable confirmation email and instantly confirm registered users?
    2. If you create new users within the PW admin back end can LoginRegisterPro send a welcome email to the user with either a password (not secure I know but a useful option for what I need it for) or a link to set their own password? Or do you need to do this yourself via hooks?
    3. Can you send users a “forgotten password” email from the PW admin back end?

    If confirmation emails are mandatory that's no big deal but for what I want it for I really need to be able to do the user management from the CMS rather than through the register part of the module.

    Thanks.

  6. I have an Images field that is set to required, maximum file = 1 and Single item (null if empty).

    When I get the page in the front-end template the field if of ProcessWire\Pageimage (singular) type as I would expect but in a Pages::saveReady hook it is ProcessWire\Pageimages (plural).

    Is this excepted behaviour — and if so, why? Is it to do with PW applying the “Single item (null if empty)” further down the chain?

    Thanks.

    EDIT: I think I have found the answer. It says this in the back-end:

    Quote

    Select the type of value you want this field to provide when accessed from the API on the front-end of your site.

    I am assuming then that because the Pages::saveReady hook is called in the back-end this isn't applied. Instead, it is added some time before the template is loaded. So, fields Files and Images will always be arrays in the back-end/unless accessed via the templates. Is that right?

  7. @Robin S Thanks again, this has been extremely helpful.

     

    I think if I use Pages::saved and ProcessPageSort::execute per your example it should cover everything I need (I am detecting non-unique values in pages/templates mimicking a database unique index). Pages::saved can be called in the site tree (AJAX) or via a standard POST when editing a page (changing status from the site tree calls this) — or even the API. As you have demonstrated if using AJAX then throwing an Exception can do the job. However, I would rather output a warning if a standard POST request and only use Vex/Exception if AJAX as the former is more flexible.

    If there any way in the Pages::saved hook to know whether it is an AJAX call or not? Is there a property in the API or do I just have to check the $_SERVER['REQUEST_PATH'] or something?

    Thank you!

  8. I need to check some data when pages are moved or saved. It runs fine when I save a page (Pages::saved) but nothing happens when I move a page (e.g. to and from trash). It only appears to be the lack of warning that is the issue. The hook definitely runs when I move pages in the site tree as I set up a simple bit of text file logging.

    wire()->addHookAfter('Pages::moved, Pages::saved', function($event) {
    	
        $event->warning('Warning');
    	
    });	

    Is it because from the site tree moving pages is done with AJAX? Is there a way to output a warning when sorting or moving pages in the site tree or is it not possible?

    Thanks.

    P.S. I have noticed on Pages::saved if you change the status from the tree view (using Unpub, Hide buttons) the hook calls but the messages are not displayed. So really I guess my question is: how can hooks send messages, errors and warnings in the tree view?

  9. For anyone who is interested I did this with the normal Page Reference field the way @Robin S suggested.

    I created a parent filter template and a child filter template (no template file and just the title field for both). I added a parent filter page and some child filters to the site tree. In the Input tab of the Page Reference field I checked Allow new pages to be created from field? Then under Selectable pages I set Parent to the page that uses the parent filter template and Template to the child filter template.

    It now works exactly as I wanted it — so thanks! ?

  10. Just as the title says really: is there a field that basically acts like a normal Select Options field but instead of having to go into Fields to add options you can do it while you're editing the page — and this then propagates to any other template that uses this field.

    I basically want to let the client add to Select Options but don't want to give them access to edit the field.

    I know I could do it by page reference/repeater but I wondered if there was a way that 1. avoids the overheard of pages and 2. where options could be added while you're editing the page rather than having to go elsewhere.

    I do have a license for ProFields but don't think there's anything there that does this.

    I hope that makes sense!

    Thanks.

  11. @BitPoet, I certainly wouldn't expect things to change on my account. Maybe the problem is not that common but I have certainly run into it a few times over the years on shared hosting. If you do work the kinks out and put it forward I would 100% vote for it. ?

    @horst, that is a great idea, thanks. I'd forgotten it was possible to do that.

    As usual, this forum is exceptional when it comes to helpful replies!

  12. Firstly, when you do a MATCH AGAINST query in MySQL you can get the score. I have found this useful in the past where you want to place more on one field over another (e.g. you may wish to place more weight on a h1 fields than a body field) as you can add a multiplier to the relevancy score.

    E.g.

    SELECT
        `h1`,
        MATCH(`h1`) AGAINST ('birth') AS `score1`,
        MATCH(`body`) AGAINST ('birth') AS `score2`
    FROM
        `pages`
    ORDER BY
        (`score1` * 2) + `score2` DESC # h1 twice as important
    LIMIT 10;

    Without resorting to raw database queries can such a thing be done using the API? I.e. with $pages->find(). I searched the docs but couldn't find anything.

    Secondly, according to https://processwire.com/docs/selectors/#sort

    Quote

    if you don't specify your own sort=property, the results are sorted according to MySQL's text searching relevance

    If your query contains more than one fulltext search does PW combine the relevancy and order by that (if you don't explicitly sort by a property)? It seems to but from my tests I can't be 100% sure.

    Thanks.

     

  13. @BitPoet, thanks so much for this.

    You are right, it doesn't use dropzone.js but it does use the term “dropzone” in the code — which confused me!

    Thanks for your code. I can see you have amended the following:

    • processwire/wire/modules/Inputfield/InputfieldFile/config.php
    • processwire/wire/modules/Inputfield/InputfieldFile/InputfieldFile.js

    If I use these modified files then I presume they will be overwritten in each PW upgrade. I don't know the process for making changes to Processwire but do you think Ryan would be open to merging this into the core? I think it's a useful feature as, particularly on shared servers, Apache can 503 if it gets too many requests too soon.

    Thanks again for your help.

  14. Thanks for posting this, I was about to as something similar. I'm not sure the “Unique” status is a good fix to what I'm after doing. It looks like a hook per @Robin S‘s code would do the job nicely.

    I love PW. One thing I do think would be nice though for a future version would be for the core to offer some of the data integrity features of a rational database but managed through template and page settings:

    • Something to mimic CASCADE and RESTRICT so that in a page reference, for example, you can restrict it being deleted if another page references it
    • Make a field (of fields) unique as above
    • Like 1
  15. It appears PW uses dropzone.js for file uploads. I have used this many times before in non-PW projects and with my hosting company I run into problems with their firewall (I think) if I upload lots of files at the same time. Basically what happens is (again, I think) their network detects a bunch of large POST requests in a short space of time and temporarily cuts you out — causing some of the uploads to fail.

    I get the same thing with PW: if I upload a lot of files together sometimes it just freezes on me with no error message.

    In my custom projects the fix was easy — just set parallelUploads to 1.

    https://www.dropzonejs.com/#config-parallelUploads

    I've searched the source and online and can't find any way of controlling how many file PW will attempts to upload at one time.

    Can I override dropzone.js anywhere and/or is there a way to control how many files PW will attempt to upload at one time?

    I accept that even with parallelUploads: 1 you could still run into this issue with multiple uploaders on one template, multiple tabs open, etc but in practice the above setting has solved the problem.

    Any ideas?

    Thanks.

  16. Thanks for this; I have not heard of that method before. It is not available on my hosting either unfortunately. It looks like it is similar to readfile() but faster. From Stack Overflow:

    Quote

    consider PHP's standard readfile() function. It won't be quite as fast as sendfiling, but it will be more widely compatible

    I was interested in knowing if there was a practical solution that didn't require PHP but I don't think there is and readfile() is probably the way to go.

    Thanks.

  17. If you want to authenticate files — and I mean properly authenticate them, not just give them a hard-to-guess name — then you could either do it with PHP or your web server (e.g. Apache) using HTTP authentication. Obviously, the latter is more efficient as it does not require PHP but it would be difficult to make work with your PHP website (e.g. with a cookie-based user login system).

    Assuming the use of PHP then and files stored outside of the website root, what is the most efficient way to do it in terms of memory use and speed?

    My gut feel is to use readfile(). According to the notes on the PHP site:

    Quote

    readfile() will not present any memory issues, even when sending large files

    Providing output buffering is off, readfile() seems suited for this and seems to be a very, very simple way to output a file outside of the web root efficiently.

    Would you use readfile() for this? I guess that if you want a user login system there is no way round not having the overhead of a language like PHP. This seems sesible to me but thought I'd ask in case there's a really obvious way I have missed.

    Thanks.

×
×
  • Create New...