Jump to content

Martijn Geerts

PW-Moderators
  • Posts

    2,769
  • Joined

  • Last visited

  • Days Won

    31

Posts posted by Martijn Geerts

  1. Hi Marc, I quit my job as developer. I really wanted to work in the outside air and with my hands again. I'm building garden sheds these days and I love it. Maybe someone wil take over some modules I made in the past.

    • Like 16
  2. When configuring a field with type Page there are several ways you can get the "selectable pages".

    • Parent
    • Template
    • Custom find...
    • Selector string
    • Custom PHP code

    I wish there was an other option:

    Pages you select

    What it should do:

    • Present a pages tree (or autocomplete)
    • Allow selecting multiple pages

    The pages you have selected, are the options in this field.

     

    pages-you-select.png

    • Like 1
  3. @Macrura First of all I love SettingsFactory!

    I've seen notices before in SettingsFactory when I add new fields but not yet saved the value.
    In this complicated setup I have here this notice prevents the PageList from being loaded.

    SettingFactory->getSettings() triggers the notice on line 152.

    // Locally i have changed the if statemaent on line 151:
    } else {
    	$newDataArray[$key] = $dataArray[$key];
    }
    
    // To this:
    } else if (isset($dataArray[$key])) {
    	$newDataArray[$key] = $dataArray[$key];
    }

    Without looking much in to this, this fixes it for me.

     

    • Like 2
  4. Quote

    I then faced an issue with edit permission in context of user template with the process module.

    yep I see, looks like PagePermissions::userEditable() returns false.

    First of all, I don't see the whole context of the repeater page thing in ProcessCroppableImage4->___execute(), I also think the solution in there doesn't work when you have nested repeaters. In ProcessCroppableImage4->___execute(), you are checking for $page->editable(). In case of the user profile $page === $this->wire('user')

    This is what I think:

       
    /**
     * Is the Page|Page->field editable?
     *
     * @param integer $pages_id
     * @param string $field
     * @return boolean
     * @throws WireExeption When not ediable
     */
    private function isEditable($pages_id = 0, $field = '') {
        $editable = false;
        /** @var Pages $pages */
        $pages = $this->wire("pages");
        /** @var User $user */
        $user = $this->wire("user");
        /** @var User $user */
        $user = $this->wire("user");
        /** @var integer $pages_id, Page Id from page being edited */
        $pages_id = (int) $pages_id;
        /** @var string $field, Croppable image fieldname */
        $field = strval($field);
    
        if (!$pages_id || !$field) return $editable;
    
        /** @var Page|NullPage */
        $page = $pages->get($pages_id);
    
        if ($page instanceof RepeaterPage) {
            while (!($page instanceof RepeaterPage)) {
                $page = $page->getForPage();
            }
        }
    
        if (!($page instanceof Page)) throw new WireException("Not a valid page");
        if (!$page->id) throw new WireException("Not a valid page");
    
        // Set Page to WireData
        $this->set("page", $page);
    
        // Returns false for user template in: PagePermissions::userEditable()
        $editable = $page->editable();
        // We need to check if the field is also editable from Page context.
        if ($editable) $editable = $page->editable($field);
        // When comming from ProcessProfile, the $page === $this->wire('user')
        if (!$editable && $page === $user) {
            // User must have profile `profile-edit` permission
            $editable = $user->hasPermission("profile-edit");
            if ($editable) {
                $pagePermissions = $this->wire("modules")->get("PagePermissions");
                // Is the field actually in the profile?
                $editable = $pagePermissions->userFieldEditable($field, $user);
            }
        }
    
        return $editable;
    }
    
    
    
    // 
    then in ProcessCroppableImage4::___execute() {
        public function ___execute() {
    
            //$this->config->scripts->add($this->config->urls->ProcessCroppableImage4 . "scripts/Jcrop/js/jquery.color.0-9-13.js");
            $this->config->scripts->add($this->config->urls->ProcessCroppableImage4 . "scripts/Jcrop/js/jquery.Jcrop.min.0-9-13.js");
            $this->config->styles->add($this->config->urls->ProcessCroppableImage4 . "scripts/Jcrop/css/jquery.Jcrop.min.0-9-13.css");
            $this->config->scripts->add($this->config->urls->ProcessCroppableImage4 . "scripts/ProcessCroppableImage4.js");
            $this->config->styles->add($this->config->urls->ProcessCroppableImage4 . "styles/ProcessCroppableImage4.css");
    
            $this->wire('processHeadline', 'Croppable Image 4');
    
            $field = $this->sanitizer->fieldName($this->input->get->field);
    
            if(preg_match("/_repeater[0-9]+$/", $field)) {
                $pages_id = (int) end((explode("_repeater", $field)));
                $field = str_replace("_repeater$pages_id", "", $field);
            } else {
                $pages_id = (int) $this->input->get->pages_id;
            }
    
            $filename = $this->sanitizer->name($this->input->get->filename);
            $height = (int) $this->input->get->height;
            $width = (int) $this->input->get->width;
            $suffix = $this->sanitizer->name($this->input->get->suffix);
    
            if($pages_id < 0 || strlen($filename) < 3) {
                $out = CroppableImage4Helpers::getTemplate("jcrop", array(
                    'invalidFieldText' => $this->getText('invalidFieldText')
                ));
                return $out->render();
            }
    
    		$editable = $this->isEditable($pages_id, $field);
    		if ($editable) $page = $this->data("page");
    		if (!$editable) throw new WireExeption("Page not editable");
    
    ......
    
    
    // In ProcessCroppableImage4::___executeSave() :
    
        public function ___executeSave() {
    
            /** Checklist: sanitisation and validation of each post param
            *
            *   [x] - [x] pages_id
            *   [x] - [x] field
            *   [x] - [x] filename
            *   [x] - [x] suffix
            *   [x] - [ ] crop
            *   [x] - [x] targetWidth
            *   [x] - [x] targetHeight
            *   [x] - [x] quality
            *   [x] - [x] sharpening
            */
    
            // get page-id from post, sanitize, validate page and edit permission
            $pages_id = intval($this->input->post->pages_id);
            // $page = wire('pages')->get($pages_id);
            // if(!$page->id) throw new WireException("Invalid page");
            // $editable = $page instanceof RepeaterPage ? $page->getForPage()->editable() : $page->editable();
            // if(!$editable) throw new WirePermissionException("Not Editable");
    
            // get fieldname from post, sanitize and validate
            $field = wire('sanitizer')->fieldName($this->input->post->field);
    
    		$editable = $this->editable($pages_id, $field);
    		if ($editable) $page = $this->data("page");
    		if (!$editable) throw new WireExeption("Page not editable");
    
    .....

     


     

     

     

     

  5. Hi @horst,

    On top of my head:

    1. Add the Croppable image field. (plain install, no update)
    2. Configure the field & attach to user template.
    3. Allow the field in ProcessProfile. (You should configure it in ProcessProfile)
    4. Go to your ProcessProfile and click the thumbnail button you configured.

    As you can see in the browser input bar when ProcessProfile is open there is no get parameters present in the URL.
    p.s. I'm open for a telephone call :-).... send you a PM with my mobile number.

     

     

    • Like 1
  6. Hi @horst,

    When using this module from the user profile, the InputfieldCroppableImage4.module cannot get the $pages_id, thus trowing an Exception.
    With the addition below you can get the $pages_id from the Process running. I did not much testing so I Don't know if it is sufficient.

    <?>php
    
    // added at line 129, InputfieldCroppableImage4.module
    
    /** @var integer $pages_id, Page ID for crop links, defaulting to 0 */
    $pages_id = 0;
    /** @var [ProcessPageEdit|ProcessUser|ProcessProfile] $process, Mixed processes maybee there are more */
    $process = $this->wire("process");
    if (method_exists($process , "getPage")) {
    		$editPage = $process->getPage();
    		if ($editPage->id) $pages_id = $editPage->id;
    }
    $pages_id = $pages_id ? $pages_id : (int) $this->input->get->id;
    
    // And I Changed the of pages_id property of the $cropUrlWithParams to the var $pages_id

    Thanks for being so active.

    • Like 1
  7. Hi @Ivan Gretsky

    The code I gonna paste here is a copy/paste from other work so there might be glitches. And you should use your own fieldnames etc.
    What you can do is:

    • Create a template and template file for RSS name it rss.
      • Template not ending with slash. (Name a the page that uses this template should end with .rss
    • In the template file something like:
    <?php namespace ProcessWire;
    
    use DomDocument;
    use DOMElement;
    use DateTime;
    
    header('Content-Type: application/xml; charset=utf-8', true);
    date_default_timezone_set("Europe/Amsterdam");
    setlocale(LC_MONETARY, 'nl_NL');
    
    /** @var \DateTime */
    $date = new DateTime('today midnight');
    
    $items = $pages->find("YOUR SEARCH SELECTOR DON'T FORGET TO SET LIMIT");
    
    /**
     * Start XML Object
     *
     * @var DOMDocument
     */
    $dom = new DOMDocument("1.0", "UTF-8");
    
    $root = $dom->appendChild($dom->createElement("rss"));
    $root->setAttribute("version","2.0");
    $root->setAttribute("xmlns:dc","http://purl.org/dc/elements/1.1/");
    $root->setAttribute("xmlns:content","http://purl.org/rss/1.0/modules/content/");
    $root->setAttribute("xmlns:atom","http://www.w3.org/2005/Atom");
    
    $link = $dom->createElement("atom:link");
    $link->setAttribute("href", $page->httpUrl());
    $link->setAttribute("rel","self");
    $link->setAttribute("type","application/rss+xml");
    
    $channel = $root->appendChild($dom->createElement("channel"));
    $channel->appendChild($link);
    $channel->appendChild($dom->createElement("title", $page->title));
    $channel->appendChild($dom->createElement("description", $page->description));
    $channel->appendChild($dom->createElement("link", $page->httpUrl));
    $channel->appendChild($dom->createElement("language", "nl"));
    $channel->appendChild($dom->createElement("lastBuildDate", $date->format(DateTime::RFC2822)));
    $channel->appendChild($dom->createElement("generator", "DomDocument, ProcessWire"));
    
    foreach ($items as $item) {
    	$dateInt = (int) $item->getUnformatted("date_start");
    	if (!$dateInt) $dateInt = (int) $item->modified;
    
    	/** @var DateTime $date */
    	$date = new DateTime(date("Y-m-d", $dateInt));
    	/** @var DOMElement $parent */
    	$itemParent = $dom->createElement("item");
    
    	// Plain tags
    	$elements = array(
    		$dom->createElement("title", $item->title),
    		$dom->createElement("description", htmlspecialchars($item->description)),
    		$dom->createElement("link", $item->httpUrl()),
    	);
    
    	// For closure
    	$image = $images->first();
    	$image = $image->size(600, round(600 * 9 / 16));
    	$mime = $image->ext === 'jpg'
    		? "image/jpeg"
    		: "image/png";
    
    	$enclosure = $dom->createElement("enclosure");
    	$enclosure->setAttribute('url', $image->httpUrl());
    	$enclosure->setAttribute('type', $mime);
    	$enclosure->setAttribute('length', $image->filesize);
    	$elements[] = $enclosure;
    
    	foreach ($elements as $element) $itemParent->appendChild($element);
    
    	$channel->appendChild($itemParent);
    }
    
    echo $dom->saveXML();

    When you want to place the RSS in the root you could hide it for non superusers:

    /**
     * Hide RSS page
     *
     * Hide RSS page int pagelist for NON superusers
     *
     */
    $wire->addHookBefore("ProcessPageList::find", function (HookEvent $event) {
    	/** @var User $user */
    	$user = $this->wire("user");
    
    	if ($user->isSuperuser()) return;
    
    	/** @var Page $page */
    	$page = $event->arguments(1);
    	/** @var string $baseSelector */
    	$baseSelector = $event->arguments(0);
    
    	$selector = $baseSelector . ", template!=rss";
    	$event->arguments(0, $selector);
    });

    Hope this could be a good starting point for you.

    • Like 2
  8. Hi Guys,

    AdminCustomFiles received some well-deserved love. (an update to version 0.9.61)

    There were several bug fixes and some major changes. I did break compatibility on several aspects of this module but after this update everything should be fine.

    - You can upgrade from 0.8.7 and below. (we take care of all settings) 
    - The JSON output is now fully customizable. 

    Previously I hooked *ProcessController::execute* and inserted the files to the config->scripts and files but with ProcessWire 3.x these were not the last files. Now we use Page::render to insert the files that should fix it.

    For the config.AdminCustomFiles javascript object we now have a base class that can be extended easily. When you created the class, you can select the class and save the module configuration. More info in the module configuration and in the example class below.

    /**
     * AcfConfigCustom
     *
     * Create a file in your AdminCustomFiles folder and start the filename with
     * ‘AcfConfig’ then ‘a custom name’ and add ‘.php’.
     *
     * In this file create a class with the basename of the file without the
     * extension. This class should extend AcfConfig and implements Module.
     *
     * Properties of the subclass
     *
     * @var AdminCustomFiles	$adminCustomFiles	Instance of AdminCustomFiles may you need it.
     * @var Page|NullPage		$editPage			In processPageEdit it would be the page you are editting.
     * @var Template			$editTemplate		Template from the page above.
     */
    class AcfConfigCustom extends AcfConfig implements Module {
    
    	/**
    	 * Optional ready method
    	 *
    	 * - Use it or leave out.
    	 * - We call ready() before calling jsConfig().
    	 */
    	public function ready() {}
    
    	/**
    	 * Required jsConfig method
    	 *
    	 * Return a PHP array ready to be used for $config->js
    	 *
    	 * @return array
    	 */
    	public function jsConfig() {
    		$process = $this->wire('process');
    		return array(
    			"activeProcess" => $process->className(),
    			"editPage" => $this->editPage->id,
    			"editTemplate" => $this->editTemplate->name,
    		);
    	}
    }

     

    • Like 4
×
×
  • Create New...