Jump to content

KarlvonKarton

Members
  • Posts

    121
  • Joined

  • Last visited

Contact Methods

  • Website URL
    www.karlvonkarton.be

Profile Information

  • Location
    Belgium
  • Interests
    Surf - Windsurf - Belgian - Music Producer - Ginger - Creative - Code

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

KarlvonKarton's Achievements

Sr. Member

Sr. Member (5/6)

52

Reputation

  1. I ended up modifying the module (FieldtypeSecureFile) of Wanze to my needs. Wanze's module doesn't delete the files nor the sub-directories where the files are in. Also, the module didn't work in the latest version of PW. Now it does, but I don't know about the old versions (and I don't care). I left out the download part and the roles, because I don't need that. I'm sure there are some things that could be approved in the code, but it works for me. I can now safely upload and delete files in a directory outside the webroot. Example: /home/username/securedir The link to the module: FieldtypeSecureFile (GitHub)
  2. I've tried to make a custom file upload module that uploads the files in a folder outside the webroot, but without succes. I tried different approaches, but not getting anywhere... Any ideas how to tackle this? approach 1: <?php namespace ProcessWire; /** * FieldtypeCustomImage * Custom fieldtype that stores images outside the web root. */ class FieldtypeOriginalFile extends FieldtypeFile { public static function getModuleInfo() { return [ 'title' => 'Original Image Field', 'version' => 1, 'summary' => 'An original image field that stores images outside the web root.', 'requires' => ['FieldtypeFile', 'InputfieldOriginalFile'], 'icon' => 'image', ]; } /** * Initialize the module and hook into Pages::saved to move files after the page is saved. */ public function init() { parent::init(); $this->addHookAfter('FieldtypeFile::customizeFilePath', $this, 'customizeFilePath'); $this->addHookAfter('FieldtypeFile::customizeFileUrl', $this, 'customizeFileUrl'); } /** * Customize the file path to store files in a folder named after the page ID. */ public function customizeFilePath(HookEvent $event) { $page = $event->argumentsByName('page'); $field = $event->argumentsByName('field'); $filename = $event->argumentsByName('file'); if ($field->name !== 'originalphoto') return; // Define the base custom storage path $baseCustomPath = '/home/portila/originalphotos/'; // Create a folder named after the page ID $customPath = $baseCustomPath . $page->id . '/'; // Ensure the directory exists if (!is_dir($customPath)) { mkdir($customPath, 0755, true); } // Return the full path to the file $event->return = $customPath . basename($filename); } /** * Customize the URL to serve files from a custom handler. */ public function customizeFileUrl(HookEvent $event) { $page = $event->argumentsByName('page'); $field = $event->argumentsByName('field'); $filename = $event->argumentsByName('file'); if ($field->name !== 'originalphoto') return; // Define the custom URL handler for files $customUrlBase = '/photo-file-handler.php?file='; $filePath = $page->id . '/' . urlencode(basename($filename)); $event->return = $customUrlBase . $filePath; } } Approach 2: <?php namespace ProcessWire; /** * FieldtypeCustomImage * Custom fieldtype that stores images outside the web root. */ class FieldtypeOriginalFile extends FieldtypeFile { public static function getModuleInfo() { return [ 'title' => 'Original Image Field', 'version' => 1, 'summary' => 'An original image field that stores images outside the web root.', 'requires' => ['FieldtypeFile', 'InputfieldOriginalFile'], 'icon' => 'image', ]; } /** * Initialize the module and hook into Pages::saved to move files after the page is saved. */ public function init() { parent::init(); $this->addHookAfter('InputfieldFile::processInputFile', $this, 'moveFilesToCustomPath'); //$this->addHookBefore('Pages::saved', $this, 'moveFilesToCustomPath'); // werkt niet, doet niets // werkt niet // $this->set('destinationPath', '/home/portila/originalphotos/'); // Set the custom path for uploaded files // hook into delete page to remove the file from the custom path $this->addHookBefore('Pages::delete', $this, 'removeCustomFile'); // Hook into Pagefile::remove to ensure files are deleted from the custom path $this->addHookBefore('Pagefile::remove', $this, 'removeCustomFile'); } public function moveFilesToCustomPath(HookEvent $event) { $pagefile = $event->argumentsByName('pagefile'); if($pagefile->field->name != 'originalphoto') return; //if($pagefile->filename == '') return; // dit is NOOIT leeg! // dus checken als file bestaat if(!file_exists($pagefile->filename)) return; $customPath = '/home/portila/originalphotos/'; $newPath = $customPath . basename($pagefile->filename); // Move the file from the assets location to the custom path if (rename($pagefile->filename, $newPath)) { // Update the file's path in ProcessWire (not in the database) //$pagefile->filename = $newPath; // Log a message the new path $this->message("The file from the custom path: $newPath"); // log message with current page id $this->message("The page id is: " . $pagefile->page->id); } else { // Log an error if the file couldn't be moved $this->error("Could not move the file to the custom path: $pagefile->filename"); } } public function removeCustomFile(HookEvent $event) { $pagefile = $event->argumentsByName('pagefile'); if($pagefile->field->name != 'originalphoto') return; $customPath = '/home/portila/originalphotos/'; // error if $pagefile->filename is empty if($pagefile->filename == '') { $this->error("The file is empty"); return; } $newPath = $customPath . basename($pagefile->filename); // Check if the file exists if (!file_exists($newPath)) { $this->error("The file does not exist at the custom path: $newPath"); return; } // Remove the file from the custom path if (@unlink($newPath)) { // Log a message if the file was removed $this->message("The file was removed from the custom path: $newPath"); } else { // Log an error if the file couldn't be removed $this->error("Could not remove the file from the custom path: $newPath"); } } }
  3. I suspected that the route I was crawling was not the correct one, so I ended up changing the course... with more succes ? field type <?php namespace ProcessWire; class FieldtypeTextZabun extends FieldtypeText implements ConfigurableModule { public static function getModuleInfo() { return array( 'title' => 'Zabun FieldtypeText', 'version' => 1, 'summary' => 'Zabun selector.', 'installs' => 'InputfieldTextZabun', 'icon' => 'home', ); } public function getInputfield(Page $page, Field $field) { $inputfield = $this->modules->get('InputfieldTextZabun'); /*$inputfield->set('zabundatabase', $this->get('zabundatabase')); $inputfield->set('zabunlocation', $this->get('zabunlocation')); $inputfield->set('zabunusername', $this->get('zabunusername')); $inputfield->set('zabunpass', $this->get('zabunpass'));*/ return $inputfield; } public static function getModuleConfigInputfields(array $data) { $inputfields = new InputfieldWrapper(); $f = wire('modules')->get('InputfieldText'); $f->attr('name', 'zabundatabase'); $f->label = __('Zabun database'); $f->icon = 'database'; $f->description = 'Zabun database'; $f->attr('value', isset($data['zabundatabase']) ? $data['zabundatabase'] : ''); $inputfields->add($f); $f = wire('modules')->get('InputfieldText'); $f->attr('name', 'zabunlocation'); $f->label = __('Zabun location'); $f->icon = 'server'; $f->description = 'Zabun location'; $f->attr('value', isset($data['zabunlocation']) ? $data['zabunlocation'] : ''); $inputfields->add($f); $f = wire('modules')->get('InputfieldText'); $f->attr('name', 'zabunusername'); $f->label = __('Zabun username'); $f->icon = 'user'; $f->description = 'Zabun username'; $f->attr('value', isset($data['zabunusername']) ? $data['zabunusername'] : ''); $inputfields->add($f); $f = wire('modules')->get('InputfieldText'); $f->attr('name', 'zabunpass'); $f->label = __('Zabun password'); $f->icon = 'key'; $f->description = 'Zabun password'; $f->attr('value', isset($data['zabunpass']) ? $data['zabunpass'] : ''); $inputfields->add($f); return $inputfields; } public function ___install() { // add dependencies copy( dirname(__FILE__).'/src/ZabunApi-master.php', $_SERVER['DOCUMENT_ROOT'].'/zabunapi.php' ); } public function ___uninstall() { // remove dependencies unlink( $_SERVER['DOCUMENT_ROOT'].'/zabunapi.php' ); } } input field: <?php namespace ProcessWire; class InputfieldTextZabun extends InputfieldText { public static function getModuleInfo() { return array( 'title' => 'Zabun InputfieldText', 'version' => 1, 'summary' => "Provides input for the Zabun Fieldtype", 'requires' => 'FieldtypeTextZabun', 'icon' => 'home', ); } public function __construct() { parent::__construct(); } public function renderReady(Inputfield $parent = null, $renderValueMode = false) { $url = 'https://unpkg.com/vue@3.2.22/dist/vue.global.prod.js'; $this->config->scripts->add($url); return parent::renderReady($parent, $renderValueMode); } public function ___render() { // $database = $this->zabundatabase; $out = '<div id="App">'; $out .= '<input '.$this->getAttributesString().' />'; $out .= '<div v-html="avar"></div>'; $out .= '</div>'; return $out; } } Thanks for reading my ramblings!
  4. The custom fieldtype / inputfield can not add a record to the inputfield table... But if I add a record manually to the inputfield table, then I can edit the value with the module. As long as I don't empty the inputfield via the module and save, because then the record is deleted by the module. I don't know what I'm doing wrong. Can someone help me? FieldtypeZabun.module : <?php namespace ProcessWire; class FieldtypeZabun extends Fieldtype implements ConfigurableModule { public static function getModuleInfo() { return array( 'title' => 'Zabun Fieldtype', 'version' => 1, 'summary' => 'Zabun selector.', 'installs' => 'InputfieldZabun', 'icon' => 'home', ); } public function __construct() { parent::__construct(); } public function sanitizeValue(Page $page, Field $field, $value) { return $value; } public function ___wakeupValue(Page $page, Field $field, $value){ return $value; } public function ___sleepValue(Page $page, Field $field, $value) { return $value; } public function getInputfield(Page $page, Field $field) { $inputfield = $this->modules->get('InputfieldZabun'); $inputfield->set('zabundatabase', $this->get('zabundatabase')); $inputfield->set('zabunlocation', $this->get('zabunlocation')); $inputfield->set('zabunusername', $this->get('zabunusername')); $inputfield->set('zabunpass', $this->get('zabunpass')); return $inputfield; } public function getCompatibleFieldtypes(Field $field){ return null; } public function getDatabaseSchema(Field $field) { $schema = parent::getDatabaseSchema($field); $schema['data'] = "TEXT NOT NULL DEFAULT ''"; $schema['keys']['data'] = 'FULLTEXT KEY `data` (`data`)'; return $schema; } public static function getModuleConfigInputfields(array $data) { $inputfields = new InputfieldWrapper(); $f = wire('modules')->get('InputfieldText'); $f->attr('name', 'zabundatabase'); $f->label = __('Zabun database'); $f->icon = 'database'; $f->description = 'Zabun database'; $f->attr('value', isset($data['zabundatabase']) ? $data['zabundatabase'] : ''); $inputfields->add($f); $f = wire('modules')->get('InputfieldText'); $f->attr('name', 'zabunlocation'); $f->label = __('Zabun location'); $f->icon = 'server'; $f->description = 'Zabun location'; $f->attr('value', isset($data['zabunlocation']) ? $data['zabunlocation'] : ''); $inputfields->add($f); $f = wire('modules')->get('InputfieldText'); $f->attr('name', 'zabunusername'); $f->label = __('Zabun username'); $f->icon = 'user'; $f->description = 'Zabun username'; $f->attr('value', isset($data['zabunusername']) ? $data['zabunusername'] : ''); $inputfields->add($f); $f = wire('modules')->get('InputfieldText'); $f->attr('name', 'zabunpass'); $f->label = __('Zabun password'); $f->icon = 'key'; $f->description = 'Zabun password'; $f->attr('value', isset($data['zabunpass']) ? $data['zabunpass'] : ''); $inputfields->add($f); return $inputfields; } } InputfieldZabun.module : <?php namespace ProcessWire; class InputfieldZabun extends Inputfield { public static function getModuleInfo() { return array( 'title' => 'Zabun Inputfield', 'version' => 1, 'summary' => "Provides input for the Zabun Fieldtype", 'requires' => 'FieldtypeZabun', 'icon' => 'home', ); } public function __construct() { //require_once(dirname(__FILE__) . '/ZabunClass.php'); $this->zabundatabase = $this->get('zabundatabase'); $this->zabunlocation = $this->get('zabunlocation'); $this->zabunusername = $this->get('zabunusername'); $this->zabunpass = $this->get('zabunpass'); parent::__construct(); } public function renderReady(Inputfield $parent = null, $renderValueMode = false) { $url = 'https://unpkg.com/vue@3.2.22/dist/vue.global.prod.js'; $this->config->scripts->add($url); return parent::renderReady($parent, $renderValueMode); } public function ___render() { $this->setAttribute('type', 'text'); $this->setAttribute('id', 'zabunselector'); $this->setAttribute('name', 'zabunselector'); $out = ''; $out .= '<div id="App"><input '.$this->getAttributesString().' /></div>'; return $out; } public function ___processInput(WireInputData $input) { parent::___processInput($input); $this->value = $input['zabunselector']; return $this; } }
  5. For a customer I needed a bunch of pictures to make a mosaic in Photoshop (cropped as a square) ? 20 lines of ProcessWire "et voila": a folder full of first pictures of every page from a certain template. <?php namespace ProcessWire; // boot api include('index.php'); // find estates from web database $estates = $pages->find("template=archief-pand"); // if estates count not zero if(count($estates)){ // loop over estates ($e is single estate) foreach($estates as $e){ // if images not null if(count($e->images)){ // get first image of estate gallery $firstPic = $e->images->first(); // resize and crop image to square 800x800px $firstPic = $firstPic->size(800,800); // if picture not null then copy picture to folder propics if(!empty($firstPic)) copy($_SERVER['DOCUMENT_ROOT'].$firstPic->url, $_SERVER['DOCUMENT_ROOT'].'/propics/'.$firstPic); } } }
  6. Is there a reason why multiLine and newlineReplacement are not in the API doc? (but still work)
  7. I have a problem with the redirects: I have one redirect: /site/be/en/ ->/projects/belgium/ But when I add another one like under, then I get error "The Redirect From URL already exists as a page path. Redirect not added. " /site/be/nl/ -> /nl/projects/belgium/ Why is this?
  8. I don't know if this is known by you guys, but when I click on "I consent" in the notice panel and then go to manage with the js-pwcmb-notice-toggle, none of the checkboxes are checked. After a refresh at least one of the checkboxes is correctly checked in the manage panel. Curiously if not clicking on "I consent" in the notice panel, but going passing by preferences instead, then everything works as expected.
  9. I guess you are commenting on sortNames? In the development it is easier for me to use a multidimensional array. It will eventually change. PS: But if it wasn't for the array, then I would never have noticed the behavior of _init.php and $LANG = ...
  10. I have done a var_dump on the variable $LANG (user logged in or not logged in). When the user is NOT logged in, then the variable is a string: string(2) "FR" When the user is logged in, then the variable is an object: object(ProcessWire\LanguagesPageFieldValue)#331 (2) { ["default"]=> string(2) "FR" ["fr"]=> string(2) "FR" } Is this a bug or not? EDIT: $LANG is only an object on the home page and when logged in...
  11. Some more info: Apparently the strange behavior only happens when a user is logged in...
  12. Is this a bug in Processwire or some PHP behavior? In _init.php there are two variables ($LANG and $sortNames): $LANG = $user->language->title; // in uppercase NL or FR $sortNames = array( 'NL' => array( 'apartment'=>'Appartement/Studio', 'house'=>'Huis/Villa', 'terrain'=>'Grond', 'parking'=>'Garage/Parkeerplaats', 'other'=>'Andere', 'commerce'=>'Commercieel' ), 'FR' => array( 'apartment'=>'Appartement/Studio', 'house'=>'Maison/Villa', 'terrain'=>'Terrain', 'parking'=>'Garage/Place', 'other'=>'Autre', 'commerce'=>'Commerce' ) ); If I use the variables in several templates, the the $LANG variable stays uppercase: echo $LANG; // gives the desired NL or FR foreach($sortNames[$LANG] as $k => $v){ echo $k.' '.$v.'<br>'; // gives the desired output from $sortNames } But if I do the same on the home template, then the $sortNames gives no output: echo $LANG; // gives the desired NL or FR foreach($sortNames[$LANG] as $k => $v){ echo $k.' '.$v.'<br>'; // stays empty !!! } The solution is simple but highly unusual, but in _init.php I done the following to correct the strange behavior: $LANG = strtoupper($user->language->title); Anyone has a clue why this is happening on home?
  13. The issue has been fixed! FYI https://github.com/processwire/processwire-issues/issues/1031
×
×
  • Create New...