-
Posts
372 -
Joined
hellomoto's Achievements
-
I guess the class needs to be called instead of the native one to implement its execute method. I added this in its construct: foreach ($this->defaultDataAddl as $k => $v) { if (!array_key_exists($k, $this->data)) $this->data[$k] = $v; } $this->addHook('ProcessPageEditImageSelect::execute', $this, '___execute'); and it has the data from the config, and the $this->page assignment changing, but it's not being called during instantiation in context, so it doesn't call any other of the object's methods needed to execute?
-
I enabled a site module extending a core module: class ProcessPageEditImageSelect_Pickpage extends ProcessPageEditImageSelect implements Module, ConfigurableModule { public static function getModuleinfo() { return [ 'title' => 'Page Edit Image pickfrompage', 'summary' => 'Extends core module: Enables specifying a default page to pick images from if the page being edited has no image fields.', 'autoload' => true, 'permission' => 'page-edit', ]; } public function __construct() { parent::__construct(); } public function init() { parent::init(); bd($this->data); } public function ___execute() {} public function getModuleConfigInputfields(array $data) { $inputfields = $this->wire(new InputfieldWrapper()); $modules = $this->wire()->modules; /** @var InputfieldPageListSelect $f */ $f = $modules->get('InputfieldPageListSelect'); $f->attr('name', 'defaultPage'); $f->attr('value', @$data['defaultPage']); $f->label = $this->_('Default page for images if no image fields'); $f->value = @$data['defaultPage']; $inputfields->add($f); /** @var InputfieldPageListSelect $f */ $f = $modules->get('InputfieldTextarea'); $f->attr('name', 'templateDefaultPage'); $f->attr('value', @$data['templateDefaultPage']); $f->label = $this->_('Default page by template for images if no image fields'); $f->notes = "1 pair of selectors `{template}:{page}` per line, e.g.,: `1:/home/`, or `home:1`, or `contact:template=home`"; $f->value = @$data['templateDefaultPage']; $inputfields->add($f); return $inputfields; } } where the execute method is the one here and the init method returns the core module's data but my execute method has no effect. What's wrong with how I'm doing it? Thank you On pages where it doesn't apply, there's an error notice from the init method of the core module: Modules: Failed to init module: ProcessPageEditImageSelect_Pickpage - No page specified but nothing shows (Tracy debugging) if not autoloaded, and ___execute has no effect either way.
-
This works to replace the ___execute method to select a default page for pages that don't contain image fields, but hooking from its own module would be a much better & drier approach but I don't know how: public function ___execute() { if($this->config->demo) throw new WireException("Sorry, image editing functions are disabled in demo mode"); if(!$this->page) { $error = "No page provided"; $this->error($error); return "<p>$error</p>"; } $sanitizer = $this->wire()->sanitizer; $modules = $this->wire()->modules; $input = $this->wire()->input; $images = $this->getImages($this->page, $this->page->fields); // locate any image fields $imageFields = $this->getImageFields($this->page); if (!wireCount($imageFields)) { $this->page = wire('pages')->get(@$this->data['defaultPage']) ?: $this->page; // Selector page by template selection in module config: $pgByTpl = function() { $lines = explode("\n", $this->data['templateDefaultPage']); foreach ($lines as $line) { $pcs = explode(':', $line); if (count($pcs) !== 2) continue; $tpl = wire('templates')->get($pcs[0]); $pg = wire('pages')->get($pcs[1]); if ($tpl->id == $this->editorPage->template->id) { return $pg; } } return false; }; $this->page = $pgByTpl() ?: $this->page; $images = $this->getImages($this->page, $this->page->fields); // locate image fields from default $imageFields = $this->getImageFields($this->page); } if(wireCount($imageFields)) { $imageFieldNames = implode(',', array_keys($imageFields)); /** @var InputfieldButton $btn */ $btn = $modules->get('InputfieldButton'); $uploadOnlyMode = "$this->page" === "$this->editorPage" ? 1 : 2; $btn->href = "../edit/?modal=1&id={$this->page->id}&fields=$imageFieldNames&uploadOnlyMode=$uploadOnlyMode"; $btn->value = $this->_('Upload Image'); $btn->addClass('upload pw-modal-button pw-modal-button-visible'); $btn->icon = 'upload'; $changes = $input->get('changes'); if($changes) { foreach(explode(',', $changes) as $name) { $name = $sanitizer->fieldName($name); $field = $this->wire()->fields->get($name); if(!$field) continue; $out .= "<script>refreshPageEditField('$name');</script>"; } } } else $btn = null; if($this->input->get('file')) return $this->executeEdit(); // initialization of variables was here $out = ''; if(wireCount($images)) { $winwidth = (int) $input->get('winwidth'); $in = $modules->get('InputfieldImage'); /** @var InputfieldImage $in */ $in->set('adminThumbs', true); $lastFieldLabel = ''; $numImageFields = 0; foreach($images as $image) { /** @var PageImage $image */ $fieldLabels = array(); $parentFields = $image->get('_parentFields'); if(!is_array($parentFields)) $parentFields = array(); foreach($parentFields as $parentField) { $fieldLabels[] = $parentField->getLabel(); } $fieldLabels[] = $image->field->getLabel(); $fieldLabel = implode(' > ', $fieldLabels); if($fieldLabel != $lastFieldLabel) { $numImageFields++; $out .= "\n\t<li class='select_images_field_label detail'>" . $sanitizer->entities($fieldLabel) . "</li>"; } $lastFieldLabel = $fieldLabel; if($this->noThumbs) { $width = $image->width(); $alt = $sanitizer->entities1($image->description); if($width > $this->maxImageWidth) $width = $this->maxImageWidth; $img = "<img src='$image->URL' width='$width' alt=\"$alt\" />"; } else { $image->set('_requireHeight', true); // recognized by InputfieldImage $info = $in->getAdminThumb($image); $img = $info['markup']; } $out .= "\n\t<li><a href='./edit?file={$image->page->id},{$image->basename}" . "&modal=1&id={$this->page->id}&winwidth=$winwidth'>$img</a></li>"; } $class = $this->noThumbs ? "" : "thumbs"; if($numImageFields > 1) $class = trim("$class multifield"); $out = "\n<ul id='select_images' class='$class'>$out\n</ul>"; } /** @var InputfieldForm $form */ $form = $modules->get("InputfieldForm"); $form->action = "./"; $form->method = "get"; /** @var InputfieldPageListSelect $field */ $field = $modules->get("InputfieldPageListSelect"); $field->label = $this->_("Images on Page:") . ' ' . $this->page->get("title") . " (" . $this->page->path . ")"; // Headline for page selection, precedes current page title/url $field->description = $this->_("If you would like to select images from another page, select the page below."); // Instruction on how to select another page $field->attr('id+name', 'page_id'); $field->value = $this->page->id; $field->parent_id = 0; $field->collapsed = wireCount($images) ? Inputfield::collapsedYes : Inputfield::collapsedNo; $field->required = true; $form->append($field); // getImageFields was here $out = $form->render() . $out; if($btn) $out .= $btn->render(); return "<div id='ProcessPageEditImageSelect'>" . $out . "\n</div>"; } Add these fields to getModuleConfigInputFields method: /** @var InputfieldPageListSelect $f */ $f = $modules->get('InputfieldPageListSelect'); $f->attr('name', 'defaultPage'); $f->attr('value', @$data['defaultPage']); $f->label = $this->_('Default Page if no image fields'); $f->value = @$data['defaultPage']; $inputfields->add($f); /** @var InputfieldPageListSelect $f */ $f = $modules->get('InputfieldTextarea'); $f->attr('name', 'templateDefaultPage'); $f->attr('value', @$data['templateDefaultPage']); $f->label = $this->_('Default page by template for images if no image fields'); $f->notes = "1 pair of selectors `{template}:{page}` per line, e.g.,: `1:/home/`, or `home:1`, or `contact:template=home`"; $f->value = @$data['templateDefaultPage']; $inputfields->add($f); Copy the entire module directory into your site modules directory.
-
This does not work: // Prevent textual input from changing, e.g., if '2020-00-01' is entered, erase $this->addHookAfter('InputfieldDatetime::processInput', function(HookEvent $event) { // Get the object the event occurred on, if needed $InputfieldDatetime = $event->object; // An 'after' hook can retrieve and/or modify the return value $return = $event->return; // Get values of arguments sent to hook (if needed) $input = $event->arguments(0); $page = $return->hasPage; $fname = $InputfieldDatetime->attributes['name']; $val = $input[$fname]; // $old = $return->hasPage->$fname; // bd(date('Y-m-d', $old)); /* Your code here, perhaps modifying the return value */ $fmt = $page->getField($fname)->dateInputFormat; // bd($fmt); $new = date('Y-m-d', strtotime($val)); if ($val == $new) return; // bd($val, $new); $this->wire->error( sprintf("Skipping field `%s` date string input: '%s' (format='%s')", $page->getField($fname)->get('label|name'), $val, $fmt) ); $return->hasPage->$fname = ''; // clear value // Populate back return value, if you have modified it $event->return = $return; }); I guess it might be better hook sanitizeValue in the Fieldtype? Sorry I'm getting very confused. The $event->return->hasPage->$fname has worked in prior tests, but I'm also confused because initially that property is set to the old value.
-
Why does this hook require saving 2x before applying the updated return value? function hookAfter_processInput(HookEvent $event) { // Get values of arguments sent to hook (if needed) $input = $event->arguments(0); $page = $event->return->hasPage; /* Your code here, perhaps modifying the return value */ $fname = $event->object->attributes['name']; $field = wire('fields')->get($fname); if (is_null($field) || !in_array($field->id, $this->data['fields'])) return; $newvalue = $input->$fname; $existing = $event->return->hasPage->$fname; $ok = $this->validate_date($newvalue, $existing); if ($ok) return; else { // Invalid: $event->return->hasPage->$fname = ''; // need to save 2x to affect ?? // $page->of(false); $page->setAndSave($fname, '', ['noHooks' => true]); // nothing $this->error("Invalid date text input for field `".$page->getField($field)->get('label|name')."`: $newvalue"); } }
-
PW date fields allow date strings such as "2020-00-01", as allowed by strtotime PHP function, but they will change upon save, with no warning. This erases the value on 1st save if it would otherwise be changed, but if it's valid, erases on 2nd save: $this->addHookAfter('InputfieldDatetime::processInput', function(HookEvent $event) { // Get the object the event occurred on, if needed $InputfieldDatetime = $event->object; // An 'after' hook can retrieve and/or modify the return value $return = $event->return; // Get values of arguments sent to hook (if needed) $input = $event->arguments(0); $fname = $InputfieldDatetime->attributes['name']; // 'dated'; $new = $input[$fname]; $old = $return->hasPage->$fname; /* Your code here, perhaps modifying the return value */ $return->hasPage->$fname = ''; // Populate back return value, if you have modified it $event->return = $return; });
-
I have a multisite PW setup with several websites on it already. I set up a new PW site separately, renamed the site directory, changed the config httpHosts, and added it to index.config.php. What could I be missing? If you can delete this post, please do, I forgot to create the host on the VM, sorry.
-
How to move pagefile to a different page via API?
hellomoto replied to hellomoto's topic in API & Templates
$np = new Page(); $np->of(false); $np->parent = $page->id; $np->template = $make; $np->title = 'tmp'; $np->addStatus('unpublished'); $np->save(); $np->uploaded->add($f); $np->title = $f->basename; $np->save(); $this->message('Uploaded to new page '.$np->id.': '.$np->title); $page->upload->delete($f); $page->save(['noHooks' => true]); works -
This did not work... $np = new Page(); $np->parent = $page; $np->template = 'upload'; $np->title = 'tmp'; $np->save(); $np->of(false); $np->uploaded->add($f); $np->title = $f->basename;//$t->description; $np->name = $sanitizer->name($np->title); $np->save(); $this->message('Uploaded to new page: '.$np->title); wire('pagefiles')->delete($f); Error: Call to a member function add() on null
-
Module: AIOM+ (All In One Minify) for CSS, LESS, JS and HTML
hellomoto replied to David Karich's topic in Modules/Plugins
Updating less.php got rid of the aforementioned LESS error though the fonts don't load anyway. Changed the JS method allowing for a second call to generate JS to be deferred: public static function JS($javascripts, $js2 = false) { // ------------------------------------------------------------------------ // Check if at least one file was passed. // ------------------------------------------------------------------------ if(empty($javascripts)) throw new WireException('There were no files specified to minimize.'); // Support passing of $config->scripts as argument which is of type FilenameArray if(($javascripts instanceof FilenameArray)) $javascripts = (array) $javascripts->getIterator(); // Convert to array // ------------------------------------------------------------------------ // Check if files exist and generating the cache file name based // on the last editing of the file. // ------------------------------------------------------------------------ $javascripts = is_array($javascripts) ? $javascripts : array($javascripts); $javascripts = self::_fileArray($javascripts, '.js'); $cacheFile = self::_getCacheName($javascripts, self::$jsCachePrefix . ($js2 ? '2' : ''), '.js'); -
Module: AIOM+ (All In One Minify) for CSS, LESS, JS and HTML
hellomoto replied to David Karich's topic in Modules/Plugins
In the document html head tag: if (!empty($jshead)) echo '<script src="'.\AIOM::JS($jshead).'"></script>'; if (!empty($jsfoot)) echo '<script src="'.\AIOM::JS($jsfoot).'" defer></script>'; ... both lines render the same file, containing only one of the files in the respective arrays (each array has one item, it only contains the 1st)? What am I doing wrong? Also, including @import google fonts begets the following error: PHP Warning: Trying to access array offset on value of type null in .../processwire/site/modules/AllInOneMinify/lib/Less/Less.php:5746 No error if I include the compiled CSS instead of LESS, but @import is used in the README examples? -
Selectors class object -- how to get string property?
hellomoto replied to hellomoto's topic in API & Templates
Okay thanks but why not just access via ->__toString()? -
Selectors class object -- how to get string property?
hellomoto replied to hellomoto's topic in API & Templates
Sorry, it's $selectors->__toString() -
I'm slowing down reading the one I'm on now.