Jump to content

taotoo

Members
  • Posts

    71
  • Joined

Posts posted by taotoo

  1. You could try the Limit Repeater module to set a max number of rows. Alternatively, I have a feeling you may also be able to set a min and max number of rows within the field setup, if so you could set them to the same number. Or maybe use the Admin On Steroids module, enable the setting for it to add CSS classes for each admin page, then add CSS via the same module to hide the add new button.

  2. On 2/16/2023 at 11:19 PM, OHP22 said:

    but our htaccess doesnt rewrite the url from png,jpg to webp?

    With method 2 htaccess should rewrite it from webp to jpg shouldn't it?

    Assuming that is what you're expecting it to do, I found the example htaccess code didn't work for me. But I found that the code below did work (of course YMMV).

    RewriteCond %{HTTP_ACCEPT} !image/webp
    RewriteRule (.+)\.webp$ $1.jpg [T=image/jpeg,E=REQUEST_image]
  3. Maybe you could see if the control panel also displays the output of php.ini somewhere, and see if it matches those values. You could also create a php.ini file, and see if those values match. I might also try uploading files of various sizes around 75mb, have the browser inspector open to see if there's any indication of when it fails, and time the failure point to see if it's something like 30s, or perhaps a multiple of 5 or 7.5 in case it's related to CPU time and the server has a multicore CPU.

    I have a similar issue when creating variations - I get the endless spinner if the creation takes longer than 15s on a dual core server.

  4. 50 minutes ago, 7Studio said:

    @taotoo thanks for a notice! I'm also on Win10 (integrated GPU, FHD display) but I can't replicate this issue on Chrome/Firefox. Could you please let me know what kind of GPU is that and what display are you using (hdpi with windows scalling)? will try to debug this further 😉 Thanks!

    Annoyingly I've just revisited the website and it's no-longer doing it! I'll check it again later. The GPU is a GTX750, and the display is low pixel density, with no scaling involved.

    • Like 1
  5. On 11/12/2022 at 8:26 PM, 7Studio said:

    continuous transitions like mouse cursor are triggered with requestAnimationFrame to avoid drops in frame rate

    On Chrome (and Firefox) on Win10 I do notice that with the browser window wider than about 1,000 pixels my mouse cursor slows down. The wider the window, the slower it gets. At 2560px wide, the mouse is at about half speed. This is with a modern CPU and also a GPU.

    • Like 1
  6. 1 hour ago, dragan said:

    Basically, you could clone the clone function (ha!) from the core and alter it slightly:

    https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/core/Pages.php#L1733

        function cloneWithoutFiles(Page $page, Page $parent = null, $recursive = true, $options = array()) {
    
            $defaults = array(
                'forceID' => 0,
                'set' => array(),
                'recursionLevel' => 0, // recursion level (internal use only)
            );
    
            if (is_string($options)) $options = Selectors::keyValueStringToArray($options);
            $options = array_merge($defaults, $options);
            if ($parent === null) $parent = $page->parent;
    
            if (count($options['set']) && !empty($options['set']['name'])) {
                $name = $options['set']['name'];
            } else {
                $name = wire()->pages->names()->uniquePageName(array(
                    'name' => $page->name,
                    'parent' => $parent
                ));
            }
    
            $of = $page->of();
            $page->of(false);
    
            // Ensure all data is loaded for the page
            foreach ($page->fieldgroup as $field) {
                // changed:
                if ($field->type !== "FieldtypeImage") {
                    if ($page->hasField($field->name)) $page->get($field->name);
                }
            }
    
            /** @var User $user */
            $user = wire()->wire('user');
    
            // clone in memory
            $copy = clone $page;
            $copy->setIsNew(true);
            $copy->of(false);
            $copy->setQuietly('_cloning', $page);
            $copy->setQuietly('id', $options['forceID'] > 1 ? (int)$options['forceID'] : 0);
            $copy->setQuietly('numChildren', 0);
            $copy->setQuietly('created', time());
            $copy->setQuietly('modified', time());
            $copy->name   = $name;
            $copy->parent = $parent;
    
            if (!isset($options['quiet']) || $options['quiet']) {
                $options['quiet'] = true;
                $copy->setQuietly('created_users_id', $user->id);
                $copy->setQuietly('modified_users_id', $user->id);
            }
    
            // set any properties indicated in options
            if (count($options['set'])) {
                foreach ($options['set'] as $key => $value) {
                    $copy->set($key, $value);
                    // quiet option required for setting modified time or user
                    if ($key === 'modified' || $key === 'modified_users_id') $options['quiet'] = true;
                }
            }
    
            // tell PW that all the data needs to be saved
            foreach ($copy->fieldgroup as $field) {
                // changed:
                if ($field->type !== "FieldtypeImage") {
                    if ($copy->hasField($field)) $copy->trackChange($field->name);
                }
            }
    
            wire()->pages->cloneReady($page, $copy);
            wire()->cloning++;
            $options['ignoreFamily'] = true; // skip family checks during clone
            try {
                wire()->pages->save($copy, $options);
            } catch (\Exception $e) {
                wire()->cloning--;
                $copy->setQuietly('_cloning', null);
                $page->of($of);
                throw $e;
            }
            wire()->cloning--;
    
            // check to make sure the clone has worked so far
            if (!$copy->id || $copy->id == $page->id) {
                $copy->setQuietly('_cloning', null);
                $page->of($of);
                return wire()->pages->newNullPage();
            }
    
            // copy $page's files over to new page
            // changed:
            // basically, you could delete this block altogether
            if (PagefilesManager::hasFiles($page)) {
    //            $copy->filesManager->init($copy);
    //            $page->filesManager->copyFiles($copy->filesManager->path());
            }
    
            // if there are children, then recursively clone them too
            if ($page->numChildren && $recursive) {
                $start             = 0;
                $limit             = 200;
                $numChildrenCopied = 0;
                do {
                    $children    = $page->children("include=all, start=$start, limit=$limit");
                    $numChildren = $children->count();
                    foreach ($children as $child) {
                        /** @var Page $child */
                        $childCopy = wire()->pages->clone($child, $copy, true, array(
                            'recursionLevel' => $options['recursionLevel'] + 1,
                        ));
                        if ($childCopy->id) $numChildrenCopied++;
                    }
                    $start += $limit;
                    wire()->pages->uncacheAll();
                } while ($numChildren);
                $copy->setQuietly('numChildren', $numChildrenCopied);
            }
    
            $copy->parentPrevious = null;
            $copy->setQuietly('_cloning', null);
    
            if ($options['recursionLevel'] === 0) {
                // update pages_parents table, only when at recursionLevel 0 since parents()->rebuild() already descends
                if ($copy->numChildren) {
                    $copy->setIsNew(true);
                    wire()->pages->parents()->rebuild($copy);
                    $copy->setIsNew(false);
                }
                // update sort
                if ($copy->parent()->sortfield() == 'sort') {
                    wire()->sortPage($copy, $copy->sort, true);
                }
            }
    
            $copy->of($of);
            $page->of($of);
            $page->meta()->copyTo($copy->id);
            $copy->resetTrackChanges();
            wire()->pages->cloned($page, $copy);
            wire()->pages->debugLog('clone', "page=$page, parent=$parent", $copy);
    
            return $copy;
        }
    
        // basic usage just as with original function:
        $pg = $pages->get(23506);
        cloneWithoutFiles($pg);

    Besides the three places marked with // changed, I also had to replace $this-> with wire()-> to use it in a template file.

    Images (files) are not copied to the new page, however, the fields are. It wouldn't be too hard to delete these after you've created the clone (after initial clone-save).

    image.thumb.png.f7b610a14f29e2aa8fdd8fbb47a3368b.png

    This works great, thank you so much!

    I noticed that your code is based on a a PW v2.7 Pages.php file. My existing PW v3 Pages.php file had in it only this cloning code:

    public function ___clone(Page $page, Page $parent = null, $recursive = true, $options = array()) {
    		return $this->editor()->_clone($page, $parent, $recursive, $options);
    	}

    I just pasted your code in below this, and it works. Not sure if that's what I'm meant to be doing or not.

    Where does PW v3 keep all its cloning code?

    1 hour ago, dragan said:

    I guess this should do the trick (delete orphaned images)

    // before the function definition:
    $imageFields = array(); // hold all image field-names
    
            // replace/insert in my above function this:
            // tell PW that all the data needs to be saved
            foreach ($copy->fieldgroup as $field) {
                if ($field->type !== "FieldtypeImage") {
                    if ($copy->hasField($field)) $copy->trackChange($field->name);
                } else {
                    $imageFields[] = $field->name; // here
                }
            }
    
    // test it:
    $pg = $pages->get(23506); // clone a page
        $newClone = cloneWithoutFiles($pg);
        $id = $newClone->id;
    //    echo "new page id = $id <br>";
        $pg = $pages->get($id);
        $pg->of(false);
        foreach($imageFields as $f) {
            $pg->$f->deleteAll();
            $pg->save($f);
        }

    Perhaps there's a cleaner way to do all this... it would be nice to have this as an option built into the core function!

    I found that I could just add the code below to the hook - it seems to prevent the contents of the field being copied over to the new page:

    $clone->image = null;
    $clone->save();
  7. 14 minutes ago, dragan said:

    Basically, you could clone the clone function (ha!) from the core and alter it slightly:

    https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/core/Pages.php#L1733

        function cloneWithoutFiles(Page $page, Page $parent = null, $recursive = true, $options = array()) {
    
            $defaults = array(
                'forceID' => 0,
                'set' => array(),
                'recursionLevel' => 0, // recursion level (internal use only)
            );
    
            if (is_string($options)) $options = Selectors::keyValueStringToArray($options);
            $options = array_merge($defaults, $options);
            if ($parent === null) $parent = $page->parent;
    
            if (count($options['set']) && !empty($options['set']['name'])) {
                $name = $options['set']['name'];
            } else {
                $name = wire()->pages->names()->uniquePageName(array(
                    'name' => $page->name,
                    'parent' => $parent
                ));
            }
    
            $of = $page->of();
            $page->of(false);
    
            // Ensure all data is loaded for the page
            foreach ($page->fieldgroup as $field) {
                // changed:
                if ($field->type !== "FieldtypeImage") {
                    if ($page->hasField($field->name)) $page->get($field->name);
                }
            }
    
            /** @var User $user */
            $user = wire()->wire('user');
    
            // clone in memory
            $copy = clone $page;
            $copy->setIsNew(true);
            $copy->of(false);
            $copy->setQuietly('_cloning', $page);
            $copy->setQuietly('id', $options['forceID'] > 1 ? (int)$options['forceID'] : 0);
            $copy->setQuietly('numChildren', 0);
            $copy->setQuietly('created', time());
            $copy->setQuietly('modified', time());
            $copy->name   = $name;
            $copy->parent = $parent;
    
            if (!isset($options['quiet']) || $options['quiet']) {
                $options['quiet'] = true;
                $copy->setQuietly('created_users_id', $user->id);
                $copy->setQuietly('modified_users_id', $user->id);
            }
    
            // set any properties indicated in options
            if (count($options['set'])) {
                foreach ($options['set'] as $key => $value) {
                    $copy->set($key, $value);
                    // quiet option required for setting modified time or user
                    if ($key === 'modified' || $key === 'modified_users_id') $options['quiet'] = true;
                }
            }
    
            // tell PW that all the data needs to be saved
            foreach ($copy->fieldgroup as $field) {
                // changed:
                if ($field->type !== "FieldtypeImage") {
                    if ($copy->hasField($field)) $copy->trackChange($field->name);
                }
            }
    
            wire()->pages->cloneReady($page, $copy);
            wire()->cloning++;
            $options['ignoreFamily'] = true; // skip family checks during clone
            try {
                wire()->pages->save($copy, $options);
            } catch (\Exception $e) {
                wire()->cloning--;
                $copy->setQuietly('_cloning', null);
                $page->of($of);
                throw $e;
            }
            wire()->cloning--;
    
            // check to make sure the clone has worked so far
            if (!$copy->id || $copy->id == $page->id) {
                $copy->setQuietly('_cloning', null);
                $page->of($of);
                return wire()->pages->newNullPage();
            }
    
            // copy $page's files over to new page
            // changed:
            // basically, you could delete this block altogether
            if (PagefilesManager::hasFiles($page)) {
    //            $copy->filesManager->init($copy);
    //            $page->filesManager->copyFiles($copy->filesManager->path());
            }
    
            // if there are children, then recursively clone them too
            if ($page->numChildren && $recursive) {
                $start             = 0;
                $limit             = 200;
                $numChildrenCopied = 0;
                do {
                    $children    = $page->children("include=all, start=$start, limit=$limit");
                    $numChildren = $children->count();
                    foreach ($children as $child) {
                        /** @var Page $child */
                        $childCopy = wire()->pages->clone($child, $copy, true, array(
                            'recursionLevel' => $options['recursionLevel'] + 1,
                        ));
                        if ($childCopy->id) $numChildrenCopied++;
                    }
                    $start += $limit;
                    wire()->pages->uncacheAll();
                } while ($numChildren);
                $copy->setQuietly('numChildren', $numChildrenCopied);
            }
    
            $copy->parentPrevious = null;
            $copy->setQuietly('_cloning', null);
    
            if ($options['recursionLevel'] === 0) {
                // update pages_parents table, only when at recursionLevel 0 since parents()->rebuild() already descends
                if ($copy->numChildren) {
                    $copy->setIsNew(true);
                    wire()->pages->parents()->rebuild($copy);
                    $copy->setIsNew(false);
                }
                // update sort
                if ($copy->parent()->sortfield() == 'sort') {
                    wire()->sortPage($copy, $copy->sort, true);
                }
            }
    
            $copy->of($of);
            $page->of($of);
            $page->meta()->copyTo($copy->id);
            $copy->resetTrackChanges();
            wire()->pages->cloned($page, $copy);
            wire()->pages->debugLog('clone', "page=$page, parent=$parent", $copy);
    
            return $copy;
        }
    
        // basic usage just as with original function:
        $pg = $pages->get(23506);
        cloneWithoutFiles($pg);

    Besides the three places marked with // changed, I also had to replace $this-> with wire()-> to use it in a template file.

    Images (files) are not copied to the new page, however, the fields are. It wouldn't be too hard to delete these after you've created the clone (after initial clone-save).

    image.thumb.png.f7b610a14f29e2aa8fdd8fbb47a3368b.png

    Ah - that's how to do it! I was looking in ProcessPageClone.module and couldn't figure out how the files were being copied...

    Thank you very much for the comprehensive answer, I'll try it out!

  8. I'm using a hook (similar to @bernhard's below) to add a Clone button when editing pages.

    Is it possible to clone the page, but without also copying over the image files?

    I tried adding this code towards the end of the hook:

    $clone->image = null;
    $clone->save();

    This successfully prevents the contents of the image field being cloned, but PW still copies the image files themselves into the new page's directory.

    I also looked at the API documentation, but it doesn't seem to provide an option for this.

    I want to avoid copying the images as there are typically about 20 files that get copied, which takes about 10 seconds on the shared server. Additionally, the first thing the client will do after cloning the page is delete the images as they will be unneeded.

     

  9. On 4/30/2019 at 2:38 AM, Noboru said:

    Hi @horst,
    My ImageSizerEngineVips is based on your ImageSizerEngineIMagickCLI with code from other sizers. The module works fine, but at the moment only for my needs, because I optimized for speed and left some options like sharpening. But if I have the time and interest, I can polish it.

    Might you make your module available @Noboru? I'd love to give it a try. 

  10. Not that I know of, though maybe it's possible to create a module to do this.

    You could instead consider using Lister. If you go to Pages > Find, you could save various searches as bookmarks, then add shortcuts to those bookmarks which would be used instead of the Page Tree. You can have different columns for each bookmarked search.

  11. You can add more fields to display by editing the templates for the relevant pages, clicking the Advanced tab, scrolling down to "List of fields to display in the admin Page List", then entering multiple fields such as {title} {a_field} {another_field}.

    You can also mix in other text, such as {title} | {a_field} > {another_field}.

  12. 2 hours ago, nbcommunication said:

    Hi @bernhardWhat complicates debugging is that the browser will use the largest image it has in the cache, so if you've loaded the page at desktop width and then try to see how it'll respond at a smaller screen size, it will still display the larger image.

    I use Firefox when debugging srcset as unlike Chrome it doesn't do this!

    • Like 3
  13. 2 minutes ago, Martinus said:

    Yes I found it. I feel so stupid. Upon installation I thought it was not mandatory to use. Now my question: is it better to use that, or do it without? I could only think about benefits such as SEO or scroll to section actions.

    I find it useful as unlike Direct Output you can define a variable in your page template and then refer to that variable in your header. I only use a single markup definition, and put all of my template code - excluding header and footer - within it.

  14. 8 hours ago, DaveP said:

    Yep, but, PW gives you methods for working with WireArrays - https://processwire.com/api/ref/functions/wire-array/. This way you can use ->first() or any of the usual methods. You'll need to refactor your code a bit but it might well be worth it.

    Thank you DaveP!

    // Otherwise get images of their book covers
    else:
    	$source = new WireArray();
    	foreach($page->page_ref_for_their_books as $a_page):
    		$source->add($a_page->images->first);		
    	endforeach;
    
    endif;
    
    echo $source->first->size(100,100)->url;

     

    • Like 1
  15. On 4/6/2022 at 11:07 PM, Macrura said:

    @taotoo

    i have experienced that and i thought i had fixed it. I will check to see if there is some change or update i forgot to commit to the repo and get back to you - it is definitely solvable if i recall.

    @Macrura@jploch

    I just updated the module and see that you've fixed it - thank you Macrura!

    On another note, I'm using Admin Theme Canvas and noticed that it and your module don't play well together, so I amended the FieldDescriptionsExtended.module file like this:

    Lines 236 and 282:
    if($this->adminTheme == 'AdminThemeUikit' or $this->adminTheme == 'AdminThemeCanvas') {
    
    Line 288:
    if($this->adminTheme != 'AdminThemeUikit' or $this->adminTheme != 'AdminThemeCanvas') {

    Not sure if that's the sort of thing you would want to include in the module or not, but will leave it here so that it's findable for others.

  16. 51 minutes ago, 3fingers said:
    // Get images of the author if they exist
    if count($page->images):
    	echo $page->images->each(function($image) {
      	return "<li><a href='$image->size(100,100)->url'>$image->description</a></li>"; // Just an output example
    });
    
    // Otherwise get images of their book covers
    else:
    	foreach($page->page_ref_for_their_books as $all_pages):
    		foreach($all_pages->images as $image):
    		echo "<li><a href='$image->size(100,100)->url'>$image->description</a></li>";
    		endforeach;
    	endforeach;
    endif;

    If possible I want to have only one section of code for the output, as in reality it's a srcset with lots going on. Though I suppose with your example I could replace the <li> with an include.

    Otherwise I was wondering if I could build an array, but neither of the two examples below seem to work (the changed lines indicated by asterisks):

    edit: I had a typo, now it seems both examples below work!

    // Get images of the author if they exist
    if $page->images !='':
    	$source = $page->images;
    
    // Otherwise get images of their book covers
    else:
    	foreach($page->page_ref_for_their_books as $a_page):
    		$an_image = $a_page->images->first;
    *		$source[] = $an_image;	*
    	endforeach;
    
    endif;
    
    foreach ($source as $source):
    	echo $source->size(100,100)->url;
    endforeach;

    Or:

    // Get images of the author if they exist
    if $page->images !='':
    	$source = $page->images;
    
    // Otherwise get images of their book covers
    else:
    	foreach($page->page_ref_for_their_books as $a_page):
    *		$source[] = $a_page->images->first;		*
    	endforeach;
    
    endif;
    
    foreach ($source as $source):
    	echo $source->size(100,100)->url;
    endforeach;
    • Like 1
  17. 1 hour ago, Micthew said:

    This is my code...
    But, when i create "else {}" and the image in data is empty, placeholder-user.png is not showing, so i re-type "$config->urls->templates.'assets/img/placeholder-user.png" to $avatar on the top variable, and then when the image in data is empty, placeholder-user.png is showing.

    I don't know whats wrong with my code, but the code is working for me.

     

    Micthew

    In my case both scenarios will have multiple images, and I want them to be output with the same img tag, within the same foreach.

    Maybe I need to change the middle section to something like this. I don't know how to do it though (a wire array maybe?):

    // Get images of the author if they exist
    if $page->images !='':
    	$source = $page->images;
    
    // Otherwise get images of their book covers
    else:
    	foreach($page->page_ref_for_their_books as $a_page):
    		$an_image = $a_page->images->first;
    	endforeach;
    	$source = every $an_image merged together to mimic the result of the first condition;
    
    endif;
    
    foreach ($source as $source):
    	echo $source->size(100,100)->url;
    endforeach;
×
×
  • Create New...