-
Posts
2,769 -
Joined
-
Last visited
-
Days Won
31
Everything posted by Martijn Geerts
-
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.
-
Type Page, Selectable pages: Pages you select
Martijn Geerts replied to Martijn Geerts's topic in Wishlist & Roadmap
You sneaky ;-), using 'Selector string' for it ! Love it, should be Core ! -
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.
-
@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.
-
Selector vs direct database search efficiency
Martijn Geerts replied to Hurme's topic in API & Templates
When requesting a page with selector you do not request other fields exept title as it is set to autojoin. -
https://processwire.com/api/ref/page/save/
-
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"); .....
-
Lister - Session bookmarks for runtime drill-down
Martijn Geerts replied to MarkE's topic in General Support
If I do understand you correctly I have build a Module for this some years ago: https://github.com/Da-Fecto/ProcessPageListerUrls Haven't used it in ages, but maybe it stil works. -
Hi @horst, On top of my head: Add the Croppable image field. (plain install, no update) Configure the field & attach to user template. Allow the field in ProcessProfile. (You should configure it in ProcessProfile) 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.
-
Hi Horst, Time flies, the oldest on secundary school now and the youngest just had her 6th birthday. Live is sweet. How are you doing?
-
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.
-
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.
-
Have not used it with PW3, now-a-days I use DomDocument
-
How to prevent an admin account from taking over the server?
Martijn Geerts replied to Anders's topic in Security
When you know your I.P. maybe you could check against that. One hook you could use is session::allowLogin -
FieldtypeSelectFile & InputfieldSelectFile
Martijn Geerts replied to Martijn Geerts's topic in Module/Plugin Development
There has been a small update on this module thanks to @Jonathan Lahijani. @Jonathan Lahijani added: PHP files can have a comment called "Description" at the top of the file which will be displayed in the dropdown if it exists. Check this option to disable it. -
Replace Inputfield with another type using Inputfield::render hook
Martijn Geerts replied to Marc's topic in API & Templates
// Could you test this??? wire()->addHookAfter('Field::getInputfield', function (HookEvent $event) { $event->return->inputfield = 'InputfieldSelect'; }); -
Updated ACF to make it compatible. (Hope this fixes it.)
-
Thanks @Macrura, I will update the module to make it backwards compatible with old PHP soon....
-
Actually I don't understand the error, the only thing I can imagine is that ext is not there... Are you willing to replace the isset line with the code above?
-
@Macrura What is $ext at that moment? Could you try to replace the isset line with: if ($ext !== 'js' && $ext !== 'css') return false;
-
Thanks @NorbertH issue has been fixed.
-
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, ); } }
-
Sorry to hear!
-
@netcarver Thanks for lookin' into this. I will take a little time this week to update the module. Thanks steve.