mirror of
https://github.com/processwire/processwire.git
synced 2025-08-09 00:06:55 +02:00
Update ProcessModule so that module installation options are now configurable from new $config->moduleInstall array. Plus update in-module instructions to describe how to install a module manually.
This commit is contained in:
@@ -1189,7 +1189,30 @@ $config->moduleServiceURL = 'https://modules.processwire.com/export-json/';
|
|||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
$config->moduleServiceKey = (__NAMESPACE__ ? 'pw300' : 'pw280');
|
$config->moduleServiceKey = 'pw301';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allowed module installation options (in admin)
|
||||||
|
*
|
||||||
|
* Module installation options you want to be available from the admin Modules > Install tab.
|
||||||
|
* For any of the options below, specify boolean `true` to allow, `false` to disallow, or
|
||||||
|
* specify string `'debug'` to allow only when ProcessWire is in debug mode.
|
||||||
|
*
|
||||||
|
* - `directory`: Allow installation or upgrades from ProcessWire modules directory?
|
||||||
|
* - `upload`: Allow installation by file upload?
|
||||||
|
* - `download`: Allow installation by file download from URL?
|
||||||
|
*
|
||||||
|
* @todo consider whether the 'directory' option should also be limited to 'debug' only.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @since 3.0.163
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$config->moduleInstall = array(
|
||||||
|
'directory' => true, // allow install from ProcessWire modules directory?
|
||||||
|
'upload' => 'debug', // allow install by module file upload?
|
||||||
|
'download' => 'debug', // allow install by download from URL?
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Substitute modules
|
* Substitute modules
|
||||||
|
@@ -130,6 +130,7 @@
|
|||||||
* @property string $moduleServiceKey API key for modules web service #pw-group-modules
|
* @property string $moduleServiceKey API key for modules web service #pw-group-modules
|
||||||
* @property bool $moduleCompile Allow use of compiled modules? #pw-group-modules
|
* @property bool $moduleCompile Allow use of compiled modules? #pw-group-modules
|
||||||
* @property array $wireMail Default WireMail module settings. #pw-group-modules
|
* @property array $wireMail Default WireMail module settings. #pw-group-modules
|
||||||
|
* @property array $moduleInstall Admin module install options you allow. #pw-group-modules
|
||||||
*
|
*
|
||||||
* @property array $substituteModules Associative array with names of substitute modules for when requested module doesn't exist #pw-group-modules
|
* @property array $substituteModules Associative array with names of substitute modules for when requested module doesn't exist #pw-group-modules
|
||||||
* @property array $logs Additional core logs to keep #pw-group-admin
|
* @property array $logs Additional core logs to keep #pw-group-admin
|
||||||
|
@@ -6,7 +6,7 @@ $(document).ready(function() {
|
|||||||
var $btn = $(".install_" + name + ":visible");
|
var $btn = $(".install_" + name + ":visible");
|
||||||
var disabled = $btn.attr('disabled');
|
var disabled = $btn.attr('disabled');
|
||||||
|
|
||||||
if($btn.size()) {
|
if($btn.length) {
|
||||||
$btn.effect('highlight', 1000);
|
$btn.effect('highlight', 1000);
|
||||||
} else {
|
} else {
|
||||||
var color = $(this).css('color');
|
var color = $(this).css('color');
|
||||||
@@ -52,7 +52,8 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("#Inputfield_new_seconds").change(function() {
|
$("#Inputfield_new_seconds").change(function() {
|
||||||
$(this).parents('form').submit();
|
$('#submit_check').removeAttr('hidden').click();
|
||||||
|
$(this).closest('form').submit();
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#wrap_upload_module").removeClass('InputfieldItemList');
|
$("#wrap_upload_module").removeClass('InputfieldItemList');
|
||||||
|
@@ -1 +1 @@
|
|||||||
$(document).ready(function(){$(".not_installed").parent("a").css("opacity",0.6).click(function(){var b=$(this).children(".not_installed").attr("data-name");var d=$(".install_"+b+":visible");var c=d.attr("disabled");if(d.size()){d.effect("highlight",1000)}else{var a=$(this).css("color");$(this).closest("tr").find(".requires").attr("data-color",$(this).css("color")).css("color",a).effect("highlight",1000)}return false});$("button.ProcessModuleSettings").click(function(){var a=$(this).parents("tr").find(".ConfigurableModule").parent("a");window.location.href=a.attr("href")+"&collapse_info=1"});if($("#modules_form").length>0){$("#modules_form").WireTabs({items:$(".Inputfields li.WireTab"),rememberTabs:true})}$("select.modules_section_select").change(function(){var b=$(this).val();var a=$(this).parent("p").siblings(".modules_section");if(b==""){a.show()}else{a.hide();a.filter(".modules_"+b).show()}document.cookie=$(this).attr("name")+"="+b;return true}).change();$(document).on("click","#head_button a",function(){document.cookie="WireTabs=tab_new_modules";return true});$("#Inputfield_new_seconds").change(function(){$(this).parents("form").submit()});$("#wrap_upload_module").removeClass("InputfieldItemList")});
|
$(document).ready(function(){$(".not_installed").parent("a").css("opacity",.6).click(function(){var name=$(this).children(".not_installed").attr("data-name");var $btn=$(".install_"+name+":visible");var disabled=$btn.attr("disabled");if($btn.length){$btn.effect("highlight",1e3)}else{var color=$(this).css("color");$(this).closest("tr").find(".requires").attr("data-color",$(this).css("color")).css("color",color).effect("highlight",1e3)}return false});$("button.ProcessModuleSettings").click(function(){var $a=$(this).parents("tr").find(".ConfigurableModule").parent("a");window.location.href=$a.attr("href")+"&collapse_info=1"});if($("#modules_form").length>0){$("#modules_form").WireTabs({items:$(".Inputfields li.WireTab"),rememberTabs:true})}$("select.modules_section_select").change(function(){var section=$(this).val();var $sections=$(this).parent("p").siblings(".modules_section");if(section==""){$sections.show()}else{$sections.hide();$sections.filter(".modules_"+section).show()}document.cookie=$(this).attr("name")+"="+section;return true}).change();$(document).on("click","#head_button a",function(){document.cookie="WireTabs=tab_new_modules";return true});$("#Inputfield_new_seconds").change(function(){$("#submit_check").removeAttr("hidden").click();$(this).closest("form").submit()});$("#wrap_upload_module").removeClass("InputfieldItemList")});
|
@@ -11,7 +11,7 @@
|
|||||||
* This version also lifts several pieces of code from Soma's Modules Manager
|
* This version also lifts several pieces of code from Soma's Modules Manager
|
||||||
* specific to the parts involved with downloading modules from the directory.
|
* specific to the parts involved with downloading modules from the directory.
|
||||||
*
|
*
|
||||||
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer
|
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
|
||||||
* https://processwire.com
|
* https://processwire.com
|
||||||
*
|
*
|
||||||
* @todo add support for module configuration inputfields with useLanguages option
|
* @todo add support for module configuration inputfields with useLanguages option
|
||||||
@@ -32,7 +32,7 @@ class ProcessModule extends Process {
|
|||||||
return array(
|
return array(
|
||||||
'title' => __('Modules', __FILE__), // getModuleInfo title
|
'title' => __('Modules', __FILE__), // getModuleInfo title
|
||||||
'summary' => __('List, edit or install/uninstall modules', __FILE__), // getModuleInfo summary
|
'summary' => __('List, edit or install/uninstall modules', __FILE__), // getModuleInfo summary
|
||||||
'version' => 118,
|
'version' => 119,
|
||||||
'permanent' => true,
|
'permanent' => true,
|
||||||
'permission' => 'module-admin',
|
'permission' => 'module-admin',
|
||||||
'useNavJSON' => true,
|
'useNavJSON' => true,
|
||||||
@@ -121,6 +121,16 @@ class ProcessModule extends Process {
|
|||||||
*/
|
*/
|
||||||
protected $numFound = 0;
|
protected $numFound = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ProcessModuleInstall|null
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $installer = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct
|
||||||
|
*
|
||||||
|
*/
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->labels['download'] = $this->_('Download');
|
$this->labels['download'] = $this->_('Download');
|
||||||
if($this->input->get('update')) {
|
if($this->input->get('update')) {
|
||||||
@@ -132,6 +142,7 @@ class ProcessModule extends Process {
|
|||||||
$this->labels['module_information'] = $this->_x("Module Information", 'edit');
|
$this->labels['module_information'] = $this->_x("Module Information", 'edit');
|
||||||
$this->labels['download_now'] = $this->_('Download Now');
|
$this->labels['download_now'] = $this->_('Download Now');
|
||||||
$this->labels['download_dir'] = $this->_('Add Module From Directory');
|
$this->labels['download_dir'] = $this->_('Add Module From Directory');
|
||||||
|
$this->labels['add_manually'] = $this->_('Add Module Manually');
|
||||||
$this->labels['upload'] = $this->_('Upload');
|
$this->labels['upload'] = $this->_('Upload');
|
||||||
$this->labels['upload_zip'] = $this->_('Add Module From Upload');
|
$this->labels['upload_zip'] = $this->_('Add Module From Upload');
|
||||||
$this->labels['download_zip'] = $this->_('Add Module From URL');
|
$this->labels['download_zip'] = $this->_('Add Module From URL');
|
||||||
@@ -156,6 +167,14 @@ class ProcessModule extends Process {
|
|||||||
require(dirname(__FILE__) . '/ProcessModuleInstall.php');
|
require(dirname(__FILE__) . '/ProcessModuleInstall.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ProcessModuleInstall
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function installer() {
|
||||||
|
if($this->installer === null) $this->installer = $this->wire(new ProcessModuleInstall());
|
||||||
|
return $this->installer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format a module version number from 999 to 9.9.9
|
* Format a module version number from 999 to 9.9.9
|
||||||
@@ -516,10 +535,21 @@ class ProcessModule extends Process {
|
|||||||
$select->required = true;
|
$select->required = true;
|
||||||
$select->attr('value', $newSeconds);
|
$select->attr('value', $newSeconds);
|
||||||
|
|
||||||
|
/** @var InputfieldSubmit $btn */
|
||||||
|
$btn = $this->modules->get('InputfieldSubmit');
|
||||||
|
$btn->attr('hidden', 'hidden');
|
||||||
|
$btn->attr('name', 'submit_check');
|
||||||
|
$btn->textFormat = Inputfield::textFormatNone;
|
||||||
|
$btn->icon = 'check';
|
||||||
|
$btn->value = ' ';
|
||||||
|
$btn->setSmall(true);
|
||||||
|
$btn->setSecondary(true);
|
||||||
|
$btn = "<button type='submit' id='submit_check' name='submit_check' value='1' hidden> </button>";
|
||||||
|
|
||||||
/** @var InputfieldMarkup $markup */
|
/** @var InputfieldMarkup $markup */
|
||||||
$markup = $this->modules->get('InputfieldMarkup');
|
$markup = $this->modules->get('InputfieldMarkup');
|
||||||
$markup->icon = 'lightbulb-o';
|
$markup->icon = 'lightbulb-o';
|
||||||
$markup->value = $select->render() . $this->renderListTable($newModulesArray, false, false, true, true);
|
$markup->value = $select->render() . ' ' . $btn . $this->renderListTable($newModulesArray, false, false, true, true);
|
||||||
$markup->label = $this->_('Recently Found and Installed Modules');
|
$markup->label = $this->_('Recently Found and Installed Modules');
|
||||||
$tab->add($markup);
|
$tab->add($markup);
|
||||||
|
|
||||||
@@ -527,88 +557,128 @@ class ProcessModule extends Process {
|
|||||||
$fieldset = $this->modules->get('InputfieldFieldset');
|
$fieldset = $this->modules->get('InputfieldFieldset');
|
||||||
$fieldset->label = $this->labels['download_dir'];
|
$fieldset->label = $this->labels['download_dir'];
|
||||||
$fieldset->icon = 'cloud-download';
|
$fieldset->icon = 'cloud-download';
|
||||||
//if($this->wire('input')->post('new_seconds')) $fieldset->collapsed = Inputfield::collapsedYes;
|
|
||||||
/** @var InputfieldName $f */
|
|
||||||
$f = $this->modules->get('InputfieldName');
|
|
||||||
$f->attr('id+name', 'download_name');
|
|
||||||
$f->label = $this->_('Module Class Name');
|
|
||||||
$f->description =
|
|
||||||
$this->_('You may browse the modules directory and locate the module you want to download and install.') . ' ' .
|
|
||||||
sprintf(
|
|
||||||
$this->_('Type or paste in the class name for the module you want to install, then click the “%s” button to proceed.'),
|
|
||||||
$this->labels['get_module_info']
|
|
||||||
);
|
|
||||||
$f->notes = $this->_('The modules directory is located at [modules.processwire.com](http://modules.processwire.com)');
|
|
||||||
$f->attr('placeholder', $this->_('ModuleClassName')); // placeholder
|
|
||||||
$f->required = false;
|
|
||||||
$fieldset->add($f);
|
|
||||||
|
|
||||||
/** @var InputfieldSubmit $f */
|
|
||||||
$f = $this->modules->get('InputfieldSubmit');
|
|
||||||
$f->attr('id+name', 'download');
|
|
||||||
$f->value = $this->labels['get_module_info'];
|
|
||||||
$f->icon = $fieldset->icon;
|
|
||||||
$fieldset->add($f);
|
|
||||||
$tab->add($fieldset);
|
$tab->add($fieldset);
|
||||||
|
//if($this->wire('input')->post('new_seconds')) $fieldset->collapsed = Inputfield::collapsedYes;
|
||||||
|
|
||||||
|
if($this->installer()->canInstallFromDirectory(false)) {
|
||||||
|
/** @var InputfieldName $f */
|
||||||
|
$f = $this->modules->get('InputfieldName');
|
||||||
|
$f->attr('id+name', 'download_name');
|
||||||
|
$f->label = $this->_('Module Class Name');
|
||||||
|
$f->description =
|
||||||
|
$this->_('You may browse the modules directory and locate the module you want to download and install.') . ' ' .
|
||||||
|
sprintf(
|
||||||
|
$this->_('Type or paste in the class name for the module you want to install, then click the “%s” button to proceed.'),
|
||||||
|
$this->labels['get_module_info']
|
||||||
|
);
|
||||||
|
$f->notes = sprintf($this->_('The modules directory is located at %s'), '[modules.processwire.com](https://modules.processwire.com)');
|
||||||
|
$f->attr('placeholder', $this->_('ModuleClassName')); // placeholder
|
||||||
|
$f->required = false;
|
||||||
|
$fieldset->add($f);
|
||||||
|
|
||||||
|
/** @var InputfieldSubmit $f */
|
||||||
|
$f = $this->modules->get('InputfieldSubmit');
|
||||||
|
$f->attr('id+name', 'download');
|
||||||
|
$f->value = $this->labels['get_module_info'];
|
||||||
|
$f->icon = $fieldset->icon;
|
||||||
|
$fieldset->add($f);
|
||||||
|
} else {
|
||||||
|
$fieldset->description = $this->installer()->installDisabledLabel('directory');
|
||||||
|
$fieldset->collapsed = Inputfield::collapsedYes;
|
||||||
|
}
|
||||||
|
|
||||||
/** @var InputfieldFieldset $fieldset */
|
/** @var InputfieldFieldset $fieldset */
|
||||||
$fieldset = $this->modules->get('InputfieldFieldset');
|
$fieldset = $this->modules->get('InputfieldFieldset');
|
||||||
$fieldset->label = $this->labels['download_zip'];
|
$fieldset->label = $this->labels['download_zip'];
|
||||||
$fieldset->icon = 'download';
|
$fieldset->icon = 'download';
|
||||||
$fieldset->collapsed = Inputfield::collapsedYes;
|
$fieldset->collapsed = Inputfield::collapsedYes;
|
||||||
|
$tab->add($fieldset);
|
||||||
$trustNote = $this->_('Be absolutely certain that you trust the source of the ZIP file.');
|
$trustNote = $this->_('Be absolutely certain that you trust the source of the ZIP file.');
|
||||||
|
|
||||||
/** @var InputfieldURL $f */
|
if($this->installer()->canInstallFromDownloadUrl(false)) {
|
||||||
$f = $this->modules->get('InputfieldURL');
|
/** @var InputfieldURL $f */
|
||||||
$f->attr('id+name', 'download_zip_url');
|
$f = $this->modules->get('InputfieldURL');
|
||||||
$f->label = $this->_('Module ZIP file URL');
|
$f->attr('id+name', 'download_zip_url');
|
||||||
$f->description = $this->_('Download a ZIP file containing a module. If you download a module that is already installed, the installed version will be overwritten with the newly downloaded version.');
|
$f->label = $this->_('Module ZIP file URL');
|
||||||
$f->notes = $trustNote;
|
$f->description = $this->_('Download a ZIP file containing a module. If you download a module that is already installed, the installed version will be overwritten with the newly downloaded version.');
|
||||||
$f->attr('placeholder', $this->_('http://domain.com/ModuleName.zip')); // placeholder
|
$f->notes = $trustNote;
|
||||||
$f->required = false;
|
$f->attr('placeholder', $this->_('http://domain.com/ModuleName.zip')); // placeholder
|
||||||
$fieldset->add($f);
|
$f->required = false;
|
||||||
|
$fieldset->add($f);
|
||||||
|
|
||||||
/** @var InputfieldSubmit $f */
|
/** @var InputfieldSubmit $f */
|
||||||
$f = $this->modules->get('InputfieldSubmit');
|
$f = $this->modules->get('InputfieldSubmit');
|
||||||
$f->attr('id+name', 'download_zip');
|
$f->attr('id+name', 'download_zip');
|
||||||
$f->value = $this->labels['download'];
|
$f->value = $this->labels['download'];
|
||||||
$f->icon = $fieldset->icon;
|
$f->icon = $fieldset->icon;
|
||||||
$fieldset->add($f);
|
$fieldset->add($f);
|
||||||
$tab->add($fieldset);
|
} else {
|
||||||
|
$fieldset->description = $this->installer()->installDisabledLabel('download');
|
||||||
|
}
|
||||||
|
|
||||||
/** @var InputfieldFieldset $fieldset */
|
/** @var InputfieldFieldset $fieldset */
|
||||||
$fieldset = $this->modules->get('InputfieldFieldset');
|
$fieldset = $this->modules->get('InputfieldFieldset');
|
||||||
$fieldset->label = $this->labels['upload_zip'];
|
$fieldset->label = $this->labels['upload_zip'];
|
||||||
$fieldset->icon = 'upload';
|
$fieldset->icon = 'upload';
|
||||||
$fieldset->collapsed = Inputfield::collapsedYes;
|
$fieldset->collapsed = Inputfield::collapsedYes;
|
||||||
|
|
||||||
/** @var InputfieldFile $f */
|
|
||||||
$f = $this->modules->get('InputfieldFile');
|
|
||||||
$f->extensions = 'zip';
|
|
||||||
$f->maxFiles = 1;
|
|
||||||
$f->descriptionRows = 0;
|
|
||||||
$f->overwrite = true;
|
|
||||||
$f->attr('id+name', 'upload_module');
|
|
||||||
$f->label = $this->_('Module ZIP File');
|
|
||||||
$f->description = $this->_('Upload a ZIP file containing module file(s). If you upload a module that is already installed, it will be overwritten with the one you upload.');
|
|
||||||
$f->notes = $trustNote;
|
|
||||||
$f->required = false;
|
|
||||||
$f->noCustomButton = true;
|
|
||||||
$fieldset->add($f);
|
|
||||||
$f = $this->modules->get('InputfieldSubmit');
|
|
||||||
$f->attr('id+name', 'upload');
|
|
||||||
$f->value = $this->labels['upload'];
|
|
||||||
$f->icon = $fieldset->icon;
|
|
||||||
$fieldset->add($f);
|
|
||||||
$tab->add($fieldset);
|
$tab->add($fieldset);
|
||||||
|
|
||||||
|
if($this->installer()->canInstallFromFileUpload(false)) {
|
||||||
|
/** @var InputfieldFile $f */
|
||||||
|
$f = $this->modules->get('InputfieldFile');
|
||||||
|
$f->extensions = 'zip';
|
||||||
|
$f->maxFiles = 1;
|
||||||
|
$f->descriptionRows = 0;
|
||||||
|
$f->overwrite = true;
|
||||||
|
$f->attr('id+name', 'upload_module');
|
||||||
|
$f->label = $this->_('Module ZIP File');
|
||||||
|
$f->description = $this->_('Upload a ZIP file containing module file(s). If you upload a module that is already installed, it will be overwritten with the one you upload.');
|
||||||
|
$f->notes = $trustNote;
|
||||||
|
$f->required = false;
|
||||||
|
$f->noCustomButton = true;
|
||||||
|
$fieldset->add($f);
|
||||||
|
$f = $this->modules->get('InputfieldSubmit');
|
||||||
|
$f->attr('id+name', 'upload');
|
||||||
|
$f->value = $this->labels['upload'];
|
||||||
|
$f->icon = $fieldset->icon;
|
||||||
|
$fieldset->add($f);
|
||||||
|
} else {
|
||||||
|
$fieldset->description = $this->installer()->installDisabledLabel('upload');
|
||||||
|
}
|
||||||
|
|
||||||
/** @var InputfieldFieldset $fieldset */
|
/** @var InputfieldFieldset $fieldset */
|
||||||
$fieldset = $this->modules->get('InputfieldFieldset');
|
$fieldset = $this->modules->get('InputfieldFieldset');
|
||||||
$fieldset->attr('id', 'fieldset_check_new');
|
$fieldset->attr('id', 'fieldset_check_new');
|
||||||
|
$fieldset->label = $this->labels['add_manually'];
|
||||||
|
$fieldset->icon = 'plug';
|
||||||
|
$fieldset->collapsed = Inputfield::collapsedYes;
|
||||||
|
$tab->add($fieldset);
|
||||||
|
|
||||||
|
/** @var InputfieldMarkup $markup */
|
||||||
|
$markup = $this->modules->get('InputfieldMarkup');
|
||||||
|
$fieldset->add($markup);
|
||||||
|
$moduleNameLabel = $this->_('ModuleName'); // Example module class/directory name
|
||||||
|
$moduleNameDir = $this->wire()->config->urls->siteModules . $moduleNameLabel . '/';
|
||||||
|
$instructions = array(
|
||||||
|
sprintf($this->_('1. Copy a module’s files into a new directory %s on the server.'), "<u>$moduleNameDir</u>") . ' * ',
|
||||||
|
sprintf($this->_('2. Click the “%s” button below, which will find the new module.'), $this->labels['reset']),
|
||||||
|
sprintf($this->_('3. Locate and click the “%s” button next to the new module.'), $this->labels['install_btn'])
|
||||||
|
);
|
||||||
|
$markup->value = '<p>' . implode('</p><p>', $instructions) . '</p>';
|
||||||
|
$markup->notes = '* ' . sprintf(
|
||||||
|
$this->_('Replace “%s” with the actual module name, which is typically its PHP class name.'),
|
||||||
|
$moduleNameLabel
|
||||||
|
);
|
||||||
|
|
||||||
|
/** @var InputfieldFieldset $fieldset */
|
||||||
|
/*
|
||||||
|
$fieldset = $this->modules->get('InputfieldFieldset');
|
||||||
|
$fieldset->attr('id', 'fieldset_check_new');
|
||||||
$fieldset->label = $this->labels['reset'];
|
$fieldset->label = $this->labels['reset'];
|
||||||
$fieldset->description = $this->_('If you have placed new modules in /site/modules/ yourself, click this button to find them.');
|
$fieldset->description = $this->_('If you have placed new modules in /site/modules/ yourself, click this button to find them.');
|
||||||
$fieldset->collapsed = Inputfield::collapsedYes;
|
$fieldset->collapsed = Inputfield::collapsedYes;
|
||||||
$fieldset->icon = 'refresh';
|
$fieldset->icon = 'refresh';
|
||||||
|
*/
|
||||||
|
|
||||||
/** @var InputfieldButton $submit */
|
/** @var InputfieldButton $submit */
|
||||||
$submit = $this->modules->get('InputfieldButton');
|
$submit = $this->modules->get('InputfieldButton');
|
||||||
@@ -617,7 +687,7 @@ class ProcessModule extends Process {
|
|||||||
$submit->showInHeader();
|
$submit->showInHeader();
|
||||||
$submit->attr('name', 'reset');
|
$submit->attr('name', 'reset');
|
||||||
$submit->attr('value', $this->labels['reset']);
|
$submit->attr('value', $this->labels['reset']);
|
||||||
$submit->icon = $fieldset->icon;
|
$submit->icon = 'refresh';
|
||||||
$fieldset->add($submit);
|
$fieldset->add($submit);
|
||||||
$tab->add($fieldset);
|
$tab->add($fieldset);
|
||||||
|
|
||||||
@@ -1010,6 +1080,11 @@ class ProcessModule extends Process {
|
|||||||
$warnings[] = $this->_('This module has no download URL specified and must be installed manually.');
|
$warnings[] = $this->_('This module has no download URL specified and must be installed manually.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!$this->installer()->canInstallFromDirectory(false)) {
|
||||||
|
$installable = false;
|
||||||
|
$markup->notes = trim($markup->notes . ' ' . $this->installer()->installDisabledLabel('directory'));
|
||||||
|
}
|
||||||
|
|
||||||
foreach($warnings as $warning) {
|
foreach($warnings as $warning) {
|
||||||
$table->row(array($this->_x('Please Note', 'install-table'), "<strong class='ui-state-error-text'> $warning</strong>"));
|
$table->row(array($this->_x('Please Note', 'install-table'), "<strong class='ui-state-error-text'> $warning</strong>"));
|
||||||
}
|
}
|
||||||
@@ -1073,9 +1148,8 @@ class ProcessModule extends Process {
|
|||||||
if(!$className) throw new WireException("No class name specified");
|
if(!$className) throw new WireException("No class name specified");
|
||||||
|
|
||||||
$destinationDir = $this->wire('config')->paths->siteModules . $className . '/';
|
$destinationDir = $this->wire('config')->paths->siteModules . $className . '/';
|
||||||
$install = $this->wire(new ProcessModuleInstall());
|
|
||||||
|
|
||||||
$completedDir = $install->downloadModule($url, $destinationDir);
|
$completedDir = $this->installer()->downloadModule($url, $destinationDir);
|
||||||
if($completedDir) {
|
if($completedDir) {
|
||||||
return $this->buildDownloadSuccessForm($className)->render();
|
return $this->buildDownloadSuccessForm($className)->render();
|
||||||
} else {
|
} else {
|
||||||
@@ -1158,15 +1232,13 @@ class ProcessModule extends Process {
|
|||||||
|
|
||||||
public function ___executeUpload($inputName = '') {
|
public function ___executeUpload($inputName = '') {
|
||||||
if(!$inputName) throw new WireException("This URL may not be accessed directly");
|
if(!$inputName) throw new WireException("This URL may not be accessed directly");
|
||||||
$install = $this->wire(new ProcessModuleInstall());
|
$this->installer()->uploadModule($inputName);
|
||||||
$install->uploadModule($inputName);
|
|
||||||
$this->session->redirect('./?reset=1');
|
$this->session->redirect('./?reset=1');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ___executeDownloadURL($url = '') {
|
public function ___executeDownloadURL($url = '') {
|
||||||
if(!$url) throw new WireException("This URL may not be accessed directly");
|
if(!$url) throw new WireException("This URL may not be accessed directly");
|
||||||
$install = $this->wire(new ProcessModuleInstall());
|
$this->installer()->downloadModuleFromUrl($url);
|
||||||
$install->downloadModule($url);
|
|
||||||
$this->session->redirect('./?reset=1');
|
$this->session->redirect('./?reset=1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
<?php namespace ProcessWire;
|
<?php namespace ProcessWire;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ProcessModuleInstall
|
* Installation helper for ProcessModule
|
||||||
*
|
*
|
||||||
* Provides methods for internative module installation for ProcessModule
|
* Provides methods for internative module installation for ProcessModule
|
||||||
*
|
*
|
||||||
|
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
|
||||||
|
* https://processwire.com
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ProcessModuleInstall extends Wire {
|
class ProcessModuleInstall extends Wire {
|
||||||
@@ -29,16 +32,30 @@ class ProcessModuleInstall extends Wire {
|
|||||||
* This primarily checks that needed dirs are writable and ZipArchive is available.
|
* This primarily checks that needed dirs are writable and ZipArchive is available.
|
||||||
*
|
*
|
||||||
* @param bool $notify Specify true to make it queue the relevant reason/error message if upload/download not supported. (default=false)
|
* @param bool $notify Specify true to make it queue the relevant reason/error message if upload/download not supported. (default=false)
|
||||||
|
* @param string $type One of 'upload' or 'download' or omit for general check
|
||||||
* @return bool
|
* @return bool
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function canUploadDownload($notify = true) {
|
public function canUploadDownload($notify = true, $type = '') {
|
||||||
|
$config = $this->wire()->config;
|
||||||
|
if($type) {
|
||||||
|
$a = $config->moduleInstall;
|
||||||
|
$allow = is_array($a) && isset($a[$type]) ? $a[$type] : false;
|
||||||
|
if($allow === 'debug' && !$config->debug) $allow = false;
|
||||||
|
if(!$allow) {
|
||||||
|
if($notify) $this->error(
|
||||||
|
sprintf($this->_('Module install option “%s”'), $type) . ' - ' .
|
||||||
|
$this->installDisabledLabel($type)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
$can = true;
|
$can = true;
|
||||||
if(!is_writable($this->config->paths->cache)) {
|
if(!is_writable($config->paths->cache)) {
|
||||||
if($notify) $this->error($this->_('Make sure /site/assets/cache/ directory is writeable for PHP.'));
|
if($notify) $this->error($this->_('Make sure /site/assets/cache/ directory is writeable for PHP.'));
|
||||||
$can = false;
|
$can = false;
|
||||||
}
|
}
|
||||||
if(!is_writable($this->config->paths->siteModules)) {
|
if(!is_writable($config->paths->siteModules)) {
|
||||||
if($notify) $this->error($this->_('Make sure your site modules directory (/site/modules/) is writeable for PHP.'));
|
if($notify) $this->error($this->_('Make sure your site modules directory (/site/modules/) is writeable for PHP.'));
|
||||||
$can = false;
|
$can = false;
|
||||||
}
|
}
|
||||||
@@ -50,6 +67,40 @@ class ProcessModuleInstall extends Wire {
|
|||||||
return $can;
|
return $can;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module upload allowed?
|
||||||
|
*
|
||||||
|
* @param bool $notify
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function canInstallFromFileUpload($notify = true) {
|
||||||
|
return $this->canUploadDownload($notify, 'upload');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module download from URL allowed?
|
||||||
|
*
|
||||||
|
* @param bool $notify
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function canInstallFromDownloadUrl($notify = true) {
|
||||||
|
return $this->canUploadDownload($notify, 'download');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module install/upgrade from directory allowed?
|
||||||
|
*
|
||||||
|
* @param bool $notify
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function canInstallFromDirectory($notify = true) {
|
||||||
|
return $this->canUploadDownload($notify, 'directory');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find all module files, recursively in Path
|
* Find all module files, recursively in Path
|
||||||
*
|
*
|
||||||
@@ -347,7 +398,7 @@ class ProcessModuleInstall extends Wire {
|
|||||||
*/
|
*/
|
||||||
public function uploadModule($inputName = 'upload_module', $destinationDir = '') {
|
public function uploadModule($inputName = 'upload_module', $destinationDir = '') {
|
||||||
|
|
||||||
if(!$this->canUploadDownload()) {
|
if(!$this->canInstallFromFileUpload()) {
|
||||||
$this->error($this->_('Unable to complete upload'));
|
$this->error($this->_('Unable to complete upload'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -381,16 +432,18 @@ class ProcessModuleInstall extends Wire {
|
|||||||
/**
|
/**
|
||||||
* Given a URL to a ZIP file, download it, unzip it, and move to /site/modules/[ModuleName]
|
* Given a URL to a ZIP file, download it, unzip it, and move to /site/modules/[ModuleName]
|
||||||
*
|
*
|
||||||
* @param $url
|
* @param string $url Download URL
|
||||||
* @param string $destinationDir Optional destination path for files (omit to auto-determine)
|
* @param string $destinationDir Optional destination path for files (omit to auto-determine)
|
||||||
|
* @param string $type Specify type of 'download' or 'directory'
|
||||||
* @return bool|string Returns destinationDir on success, false on failure.
|
* @return bool|string Returns destinationDir on success, false on failure.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function downloadModule($url, $destinationDir = '') {
|
public function downloadModule($url, $destinationDir = '', $type = 'download') {
|
||||||
|
|
||||||
if(!$this->canUploadDownload()) {
|
if($type === 'directory') {
|
||||||
$this->error($this->_('Unable to complete download'));
|
if(!$this->canInstallFromDirectory()) return false;
|
||||||
return false;
|
} else {
|
||||||
|
if(!$this->canInstallFromDownloadUrl()) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!preg_match('{^https?://}i', $url)) {
|
if(!preg_match('{^https?://}i', $url)) {
|
||||||
@@ -425,6 +478,60 @@ class ProcessModuleInstall extends Wire {
|
|||||||
return $success ? $destinationDir : false;
|
return $success ? $destinationDir : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download module from URL
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param string $destinationDir
|
||||||
|
* @return bool|string
|
||||||
|
* @since 3.0.162
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function downloadModuleFromUrl($url, $destinationDir = '') {
|
||||||
|
return $this->downloadModule($url, $destinationDir, 'download');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download module from directory
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param string $destinationDir
|
||||||
|
* @return bool|string
|
||||||
|
* @since 3.0.162
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function downloadModuleFromDirectory($url, $destinationDir = '') {
|
||||||
|
return $this->downloadModule($url, $destinationDir, 'directory');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return label to indicate option is disabled and how to enable it
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @return string
|
||||||
|
* @since 3.0.162
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function installDisabledLabel($type) {
|
||||||
|
$config = $this->wire()->config;
|
||||||
|
$a = $config->moduleInstall;
|
||||||
|
$debug = !empty($a[$type]) && $a[$type] === 'debug';
|
||||||
|
$opt1 = "`\$config->moduleInstall('$type', true);` " . $this->_('to enable always');
|
||||||
|
$opt2 = "`\$config->debug = true;` " . $this->_('temporarily');
|
||||||
|
$opt3 = "`\$config->moduleInstall('$type', 'debug');` " . $this->_('to enable in debug mode only');
|
||||||
|
$file = $config->urls->site . 'config.php';
|
||||||
|
$inst = $this->_('To enable, edit file %1$s and specify: %2$s …or… %3$s');
|
||||||
|
if($debug) {
|
||||||
|
return
|
||||||
|
$this->_('This install option is configured to be available only in debug mode.') . ' ' .
|
||||||
|
sprintf($inst, "$file", "\n$opt2", "\n$opt1");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
$this->_('This install option is currently disabled.') . ' ' .
|
||||||
|
sprintf($inst, "$file", "\n$opt1", "\n$opt3");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user