alpham8 Posted September 25 Share Posted September 25 Hi, I'm trying to get some basic knowledge of Processwire module development. I've read the beginner guides and I've done a lot of research. My current use case is to extend a custom admin template for pages with an update button in the "settings" tab of this template. The update button should then update the page's data through an external API on this page using its metadata that this template type has when you edit the page in the admin. Here's the shortened PHP code (yes, I've build own classes for the hooks) of what I trying to achieve that comes along with a few problems: <?php namespace ProcessWire; class TestUpdate extends Process implements ConfigurableModule { public const XHR_PAGE_NAME = 'test-update'; public const JSON_TPL_NAME = 'json'; public static function getModuleInfo() { return [ 'title' => 'My Admin Extender', 'summary' => 'An admin module to easily bring test data up-to-date', 'version' => '0.0.1', 'permission' => 'test-update', 'permissions' => [ 'test-update' => 'View the button in the template', 'test-update-save' => 'Permission to perform the actual update from API', ], 'icon' => 'table', 'author' => 'alpham8', 'requires' => 'UpdatePlugin>=0.0.1, ProcessWire>=3.0.133', 'page' => [ 'name' => self::XHR_PAGE_NAME, 'title' => 'update-product', 'template' => 'admin' ] ]; } public function ready() { /** @var Page $page */ $page = $this->wire('page'); // add helper notices about ProCache to page and template editors if (static::isTemplate('admin', $page)) { $this->addHookAfter('ProcessPageEdit::buildFormSettings', $this, 'hookPageEdit'); } } public function hookPageEdit(HookEvent $event) { /** @var WirePageEditor $process */ $process = $event->object; $page = $process->getPage(); if (static::isTemplate('product', $page)) { // TODO: maybe add $this->user->isSuperuser() check $form = $event->return; /** @var InputfieldMarkup $field */ $field = $this->modules->get("InputfieldMarkup"); $info = HaroImportProductPages::getModuleInfo(); $field->label = $info['title']; $field->icon = $info['icon']; /** @var InputfieldButton $btn */ $btn = $this->modules->get('InputfieldButton'); $btn->attr('value', 'update product data'); if ($page->hasField('param1') && $page->hasField('param2')) { $btn->attr( 'href', '#' ); $btn->addClass('update-link'); $btn->attr('data-param1', $page->get('param1')); $btn->attr('data-url', 'https://' . $_SERVER['HTTP_HOST'] . '/processwire/test-update/save/'); } $btn->icon = 'refresh'; $btn->attr('id+name', 'UpdateProductPagesBtn'); $btn->label = 'Update product data'; $btn->collapsed = Inputfield::collapsedNever; $field->collapsed = Inputfield::collapsedNever; $field->attr('value', $btn->render()); $form->add($field); } } /** * Does user have permission? * * @param string $name * @return bool * @throws WireException */ protected function hasPermission(string $name): bool { $user = $this->wire()->user; if ($user->isSuperuser()) { return true; } return $user->hasPermission($name); } public function execute(): array|string { return 'test1'; } public function executeSave(): array|string { $input = $this->wire()->input; $testparam = $input->post('testparam'); $result = false; /** @var UpdatePlugin $module */ $module = $this->wire->modules->get('UpdatePlugin'); // possibly product number check: if ($testparam !== '' && is_numeric($testparam) && \mb_strlen($testparam, 'UTF-8') >= 4) { $result = $module->writeDataToPage($testparam); } return json_encode([ 'testparam' => $testparam, 'success' => $result === 1, ]); } } My problems or questions are: 1st The ready method doesn't get called in an admin module, instead, I need to place it in another module like this: <?php namespace ProcessWire; class UpdatePlugin extends Wire implements Module { public static function getModuleInfo() { return [ 'title' => 'UpdatePlugin', 'version' => '0.0.1', 'summary' => 'Summary for UpdatePlugin ...', 'author' => 'alpham8', 'icon' => 'table', 'autoload' => true, 'requires' => 'ProcessWire>=3.0.123', ]; } public function init() { $scriptUrl = $this->urls->$this . 'assets/product-update.js'; $this->config->scripts->add($scriptUrl); } public function ready() { /** @var Page $page */ $page = $this->wire('page'); // add helper notices about ProCache to page and template editors if (static::isTemplate('admin', $page)) { $this->addHookAfter('ProcessPageEdit::buildFormSettings', $this, 'hookPageEdit'); } } // [see above] ... } 2nd Isn't there a way to just build an ajax request that returns plain JSON without that page / template skeleton? As far as I understood it, a page is mandatory in Processwire for this. That would be fine, if we can hide the page in the admin's navbar by using css. I thought that might be possible with creating an own template that just outputs JSON, right? But how to do a template without a parent one? 3rd How can I bring or access variables from modules in pages? Just by calling it without the knowledge that they are exist on the concrete (PHP) page? 4th Isn't there a way to get the absolute URL out of $config->urls ? I'd like to avoid that insecure $_SERVER['HTTP_HOST'] call. We're currently on ProcessWire 3.0.210. An update is planned after that modules. Any help to that above question would be great. Thanks in advice, alpham8 1 Link to comment Share on other sites More sharing options...
bernhard Posted September 25 Share Posted September 25 2 hours ago, alpham8 said: 2nd Isn't there a way to just build an ajax request that returns plain JSON without that page / template skeleton? As far as I understood it, a page is mandatory in Processwire for this. That would be fine, if we can hide the page in the admin's navbar by using css. I thought that might be possible with creating an own template that just outputs JSON, right? But how to do a template without a parent one? Sorry don't have more time for the other questions but this one is quickly answered: https://processwire.com/blog/posts/pw-3.0.173/ 2 Link to comment Share on other sites More sharing options...
Jan Romero Posted September 25 Share Posted September 25 (edited) 3 hours ago, alpham8 said: 1st The ready method doesn't get called in an admin module Can’t you autoload your Process module? https://processwire.com/docs/modules/development/#automatically-loading-modules If you set 'autoload' => 'template=admin' in getModuleInfo() the ready() method should be called on every request within the PW admin. You can then determine if your hooks are needed as you’re already doing. 3 hours ago, alpham8 said: 3rd How can I bring or access variables from modules in pages? Just by calling it without the knowledge that they are exist on the concrete (PHP) page? I'm not sure what you mean by this, but you can use $modules->get('TestUpdate') to get an instance of your module? 3 hours ago, alpham8 said: 4th Isn't there a way to get the absolute URL out of $config->urls ? I'd like to avoid that insecure $_SERVER['HTTP_HOST'] call. Yes, you can use $config->urls->admin, for example, but since you're creating a Process module, you should be able to get the entire URL using $this->getProcessPage(). That should be way to go since users can theoretically move or rename your Process page (as well as the Admin itself). If you're inside a request to the Process page, it will get you the current Page. Otherwise it will get the first page using the Process. Edited September 25 by Jan Romero 2 Link to comment Share on other sites More sharing options...
alpham8 Posted October 25 Author Share Posted October 25 Hi again, and sorry for my late reply. Your answers have helped me well, thank you! 🙂 I will try to go through every answer: On 9/25/2024 at 6:38 PM, Jan Romero said: Can’t you autoload your Process module? https://processwire.com/docs/modules/development/#automatically-loading-modules If you set 'autoload' => 'template=admin' in getModuleInfo() the ready() method should be called on every request within the PW admin. You can then determine if your hooks are needed as you’re already doing. Yes, that's true, I need autoload here. On 9/25/2024 at 6:38 PM, Jan Romero said: I'm not sure what you mean by this, but you can use $modules->get('TestUpdate') to get an instance of your module? This was simply to my missing knowledge of what you can code in a template. My question was how can we access those variables, that are returned by module methods, if we imagine, that we are currently inside site/templates/home.php, an stripped down example: <?php namespace ProcessWire; // Template file for “home” template used by the homepage /** @var Page $page */ /** @var Pages $pages */ /** @var Config $config */ ?> <?php include '_header.php'; ?> <section id="home" class="overflow-clip"> <!-- Projekte --> <div class="position-relative d-flex mb-120px-xs-70px py-210px pb-0"> <div class="container"> <div class="row d-flex"> <div class="col-7 col-md-5"> <div class="pb-15px heading-large"> <?php echo $page->heading_slider; ?> </div> </div> </div> </div> </div> <a href="<?php echo $pages->get(1466)->url; ?>#heading" class="inner"> <img src="<?php echo $config->urls->templates; ?>media/images/icon.svg" alt="icon rocket"> <div class="text-center">Our advantages</div> </a> </section> <?php include '_footer.php'; ?> So, at home.php template we can use there $page, $pages, $config and every other variable that a module might inject. And of course, from page with dot notation every field that this page have. There are two types of fields: system-wide fields, that are loaded on every request and page-fields which are only loaded when the concrete page is loaded and those fields on this page are requested to be loaded. Fields are always copied into a page, so there's not a reference or foreign key relation to the origin field. Thank you, got it! On 9/25/2024 at 6:38 PM, Jan Romero said: Yes, you can use $config->urls->admin, for example, but since you're creating a Process module, you should be able to get the entire URL using $this->getProcessPage(). That should be way to go since users can theoretically move or rename your Process page (as well as the Admin itself). If you're inside a request to the Process page, it will get you the current Page. Otherwise it will get the first page using the Process. I've done this. Unfortunately, this provides us relative URLs. I have had needed absolute URLs. However, I managed to use the relative URL here. On 9/25/2024 at 5:41 PM, bernhard said: Sorry don't have more time for the other questions but this one is quickly answered: https://processwire.com/blog/posts/pw-3.0.173/ That was exactly, what I was looking for, thank you so much! 🙂 I've used this multiple times. I needed to get used with the ProcessWire's own Callable syntax, but now it's working. Thank you again all, this topic can be closed. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now