Quantcast

[Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]

Jonny Bradley-4
Hi all

This is a quite big change for Tiki 17, and really quite overdue and needed for the list plugin GUI, which i'm hoping now to add before we branch (for which thank you Marc!)

Plugin edit forms are now created sever-side so we can use a template (templates/plugin/edit.tpl) to build the form and all the goodness of a php service lib/core/Services/Edit/PluginController.php for processing it. Rather than re-creating the ancient custom js validation i've used the jquery validator (if the feature is enabled) which i think works better and will be more useful in the future.

In the future we should be able to extend this method for editing plugins to other objects, not just wiki pages.

Anyway, as with many of these big changes there isn't a huge amount to see that's new (yet) and something somewhere is bound to have borken so please do let me know if you find anything related to this that's fallen off!

Thanks,

jonny




> On 13 Mar 2017, at 14:58, [hidden email] wrote:
>
> Revision: 61664
>          http://sourceforge.net/p/tikiwiki/code/61664
> Author:   jonnybradley
> Date:     2017-03-13 14:58:28 +0000 (Mon, 13 Mar 2017)
> Log Message:
> -----------
> [MOD] plugins: Move plugin edit form processing to a serverside AJAX service.
> TODO Switch over remaining usages of tiki-wikiplugin_edit.php to service plugin replace and remove that and tiki*js.php files
> Probably further tidying up and fixes to do too, please advice of any breakages (thanks marcalporte)
>
> Modified Paths:
> --------------
>    trunk/lib/core/Services/Edit/PluginController.php
>    trunk/lib/jquery_tiki/tiki-pluginedit.js
>    trunk/tiki-wikiplugin_edit.php
>
> Added Paths:
> -----------
>    trunk/templates/plugin/edit.tpl
>
> Modified: trunk/lib/core/Services/Edit/PluginController.php
> ===================================================================
> --- trunk/lib/core/Services/Edit/PluginController.php 2017-03-13 12:09:36 UTC (rev 61663)
> +++ trunk/lib/core/Services/Edit/PluginController.php 2017-03-13 14:58:28 UTC (rev 61664)
> @@ -17,7 +17,7 @@
>
> function __construct()
> {
> - $this->parserlib = TikiLib::lib('parser');
> + $this->pluginList = [];
> }
>
> function setUp()
> @@ -27,7 +27,12 @@
> $this->pluginList = TikiLib::lib('wiki')->list_plugins(true);
> }
>
> -
> + /**
> + * List all or some of theplugins for the textarea control panel
> + *
> + * @param JitFilter $input
> + * @return array
> + */
> function action_list($input)
> {
> $filter = $input->filter->text();
> @@ -41,7 +46,7 @@
> }
> $results = TikiLib::lib('prefs')->getMatchingPreferences($query);
>
> - foreach($results as $result) {
> + foreach ($results as $result) {
> if (strpos($result, 'wikiplugin_') === 0) {
> $key = strtoupper(substr($result, 11));
> $arr = array_filter($this->pluginList, function ($plugin) use ($key) {
> @@ -72,6 +77,214 @@
> );
> }
>
> + /**
> + * Display plugin edit form or process saving changes
> + *
> + * @param JitFilter $input
> + * @return array
> + * @throws Services_Exception_BadRequest
> + * @throws Services_Exception_Denied
> + */
> + function action_edit($input)
> + {
> + global $prefs;
> +
> + $parserlib = TikiLib::lib('parser');
> +
> + $area_id = $input->area_id->alnumdash();
> + $type = $input->type->word();
> + $index = $input->index->int();
> + $page = $input->page->pagename();
> + $pluginArgs = $input->pluginArgs->array();
> + $bodyContent = $input->bodyContent->wikicontent();
> + $edit_icon = $input->edit_icon->text();
> + $selectedMod = $input->selectedMod->text();
> +
> + $tikilib = TikiLib::lib('tiki');
> + $pageInfo = $tikilib->get_page_info($page);
> + if (! $pageInfo) {
> + // in edit mode
> + } else {
> + $perms = $tikilib->get_perm_object($page, 'wiki page', $pageInfo, false);
> + if ($perms['tiki_p_edit'] !== 'y') {
> + throw new Services_Exception_Denied(tr('You do not have permission to edit "%0"', $page));
> + }
> + }
> +
> +
> + if ($_SERVER['REQUEST_METHOD'] === 'POST') {
> +
> + $this->action_replace($input);
> +
> + return [
> + 'redirect' => TikiLib::lib('wiki')->sefurl($page),
> + ];
> +
> + } else {        // render the form
> +
> + $info = $parserlib->plugin_info($type);
> + $info['advancedParams'] = [];
> + $validationRules = [];
> +
> + foreach ($info['params'] as $key => $param) {
> + if ($prefs['feature_jquery_validation'] === 'y') {
> + // $("#insertItemForm4").validate({rules: { ins_11: { required: true}, ins_13: { remote: { url: "validate-ajax.php", type: "post", data: { validator: "distinct", parameter: "trackerId=4&fieldId=13&itemId=0", message: "", input: function() { return $("#ins_13").val(); } } } }, ins_18: { required: true, remote: { url: "validate-ajax.php", type: "post", data: { validator: "distinct", parameter: "trackerId=4&fieldId=18&itemId=0", message: "this is not distinct!", input: function() { return $("#ins_18").val(); } } } }}, messages: { ins_11: { required: "This field is required" }, ins_18: { required: "this is not distinct!" }},
> + if ($param['required']) {
> + if (empty($param['parent'])) {
> + $validationRules["params[$key]"] = ['required' => true];
> + } else {
> + $validationRules["params[$key]"] = ['required_in_group' => [
> + 1,
> + '.group-' . $param['parent']['name'],
> + 'other',
> + ]];
> + }
> + }
> + }
> + if (! empty($param['advanced']) && ! isset($pluginArgs[$key]) && empty($param['parent'])) {
> + $info['advancedParams'][$key] = $param;
> + unset($info['params'][$key]);
> + }
> + }
> +
> + if ($validationRules) {
> + $rules = json_encode(['rules' => $validationRules]);
> + TikiLib::lib('header')->add_jq_onready('$("#plugin_params > form").validate(' . $rules . ');');
> + }
> +
> + if ($type === 'module' && isset($pluginArgs['module'])) {
> + if ($selectedMod) {
> + $pluginArgs['module'] = $selectedMod;
> + }
> + $file = 'modules/mod-func-' . $pluginArgs['module'] . '.php';
> + if (file_exists($file)) {
> + include_once($file);
> + $info_func = "module_{$pluginArgs['module']}_info";
> + if (function_exists($info_func)) {
> + $moduleInfo = $info_func();
> + if (isset($info['params']['max'])) {
> + $max = $info['params']['max'];
> + unset($info['params']['max']); // move "max" to last
> + }
> + foreach($moduleInfo['params'] as $key => $value) {
> + $info['params'][$key] = $value;
> + }
> + if (! empty($max)) {
> + $info['params']['max'] = $max;
> + }
> + // replace the module plugin description with the one from the select module
> + $info['params']['module']['description'] = $moduleInfo['description'];
> + }
> +
> + }
> + }
> +
> + return [
> + // pass back the input parameters
> + 'area_id' => $area_id,
> + 'type' => $type,
> + 'index' => $index,
> + 'pageName' => $page,
> + 'pluginArgs' => $pluginArgs,
> + 'pluginArgsJSON' => json_encode($pluginArgs),
> + 'bodyContent' => $bodyContent,
> + 'edit_icon' => $edit_icon,
> + 'selectedMod' => $selectedMod,
> +
> + 'info' => $info,
> + 'title' => $type,
> + ];
> + }
> + }
> +
> + /**
> + * Replace plugin in wiki content
> + * Migrated from tiki-wikiplugin_edit.php
> + *
> + * @param JitFilter $input
> + * @return array
> + * @throws Services_Exception
> + * @throws Services_Exception_BadRequest
> + * @throws Services_Exception_Denied
> + */
> + function action_replace($input)
> + {
> + global $user;
> +
> + $tikilib = TikiLib::lib('tiki');
> + $parserlib = TikiLib::lib('parser');
> +
> + $page = $input->page->pagename();
> + $type = $input->type->word();
> + $message = $input->message->text();
> + $content = $input->content->wikicontent();
> + $index = $input->index->int();
> + $params = $input->params->array();
> +
> + $referer = $_SERVER['HTTP_REFERER'];
> +
> + if (! $page || ! $type || ! $referer || $_SERVER['REQUEST_METHOD'] !== 'POST') {
> + throw new Services_Exception(tr('Missing parameters'));
> + }
> +
> + $plugin = strtolower($type);
> + $meta = $parserlib->plugin_info($plugin);
> +
> + if (! $page || ! $type || ! $referer) {
> + throw new Services_Exception(tr('Plugin "%0" not found', $plugin));
> + }
> +
> + if (! $message) {
> + $message = tr('%0 Plugin modified by editor.', $plugin);
> + }
> +
> + $info = $tikilib->get_page_info($page);
> + if (! $info) {
> + throw new Services_Exception_BadRequest(tr('Page "%0" not found', $page));
> + }
> +
> + $perms = $tikilib->get_perm_object($page, 'wiki page', $info, false);
> + if ($perms['tiki_p_edit'] !== 'y') {
> + throw new Services_Exception_Denied(tr('You do not have permission to edit "%0"', $page));
> + }
> +
> + $current = $info['data'];
> +
> + $matches = WikiParser_PluginMatcher::match($current);
> + $count = 0;
> + foreach ($matches as $match) {
> + if ($match->getName() !== $plugin) {
> + continue;
> + }
> +
> + ++$count;
> +
> + if ($index === $count) {
> + // by using content of "~same~", it will not replace the body that is there
> + $content = ($content == "~same~" ? $match->getBody() : $content);
> +
> + if (! $params) {
> + $params = $match->getArguments();
> + }
> +
> + $match->replaceWithPlugin($plugin, $params, $content);
> +
> + $tikilib->update_page(
> + $page,
> + $matches->getText(),
> + $message,
> + $user,
> + $tikilib->get_ip_address()
> + );
> +
> + break;
> + }
> + }
> +
> + return [];
> +
> + }
> +
> }
>
>
>
> Modified: trunk/lib/jquery_tiki/tiki-pluginedit.js
> ===================================================================
> --- trunk/lib/jquery_tiki/tiki-pluginedit.js 2017-03-13 12:09:36 UTC (rev 61663)
> +++ trunk/lib/jquery_tiki/tiki-pluginedit.js 2017-03-13 14:58:28 UTC (rev 61664)
> @@ -82,137 +82,30 @@
> replaceText = false;
> }
> }
> - var form = build_plugin_form(type, index, pageName, pluginArgs, bodyContent, selectedMod);
>
> - //with PluginModule, if the user selects another module while the edit form is open
> - //replace the form with a new one with fields to match the parameters for the module selected
> - $(form).find('tr select[name="params[module]"]').change(function () {
> - var npluginArgs = $.parseJSON($(form).find('input[name="args"][type="hidden"]').val());
> - //this is the newly selected module
> - var selectedMod = $(form).find('tr select[name="params[module]"]').val();
> - $('div.plugin input[name="type"][value="' + type + '"]').parent().parent().remove();
> - popupPluginForm(area_id, type, index, pageName, npluginArgs, bodyContent, edit_icon, selectedMod);
> - });
> - var $form = $(form).find('tr input[type=submit]').remove();
> -
> - container.append(form);
> -
> -
> - var pfc = container.find('table tr').length; // number of rows (plugin form contents)
> - var t = container.find('textarea:visible').length;
> - if (t) {
> - pfc += t * 3;
> - }
> - if (pfc > 9) {
> - pfc = 9;
> - }
> - if (pfc < 2) {
> - pfc = 2;
> - }
> - pfc = pfc / 10; // factor to scale dialog height
> -
> - var $closeBtn = $('<button>')
> - .text(tr("Close"))
> - .addClass('btn btn-default')
> - .click(function () {
> - $(this).parents(".modal").modal("hide");
> - });
> -
> - var $submitBtn = $('<button>')
> - .text(replaceText ? tr("Replace") : edit_icon ? tr("Submit") : tr("Insert"))
> - .addClass('btn btn-primary')
> - .click(function () {
> -
> - $(this).off("click").css("opacity", 0.3);
> -
> - var meta = tiki_plugins[type];
> - var params = [];
> - var edit = edit_icon;
> - // whether empty required params exist or not
> - var emptyRequiredParam = false;
> -
> - for (var i = 0; i < form.elements.length; i++) {
> - var element = form.elements[i].name;
> -
> - var matches = element.match(/params\[(.*)\]/);
> -
> - if (matches === null) {
> - // it's not a parameter, skip
> - continue;
> - }
> - var param = matches[1];
> -
> - var val = form.elements[i].value;
> -
> - // check if fields that are required and visible are not empty
> - if (meta.params[param]) {
> - if (meta.params[param].required) {
> - if (val === '' && $(form.elements[i]).is(':visible')) {
> - $(form.elements[i]).css('border-color', 'red');
> - if ($(form.elements[i]).next('.required_param').length === 0) {
> - $(form.elements[i]).after('<div class="required_param" style="font-size: x-small; color: red;">(required)</div>');
> - }
> - emptyRequiredParam = true;
> - }
> - else {
> - // remove required feedback if present
> - $(form.elements[i]).css('border-color', '');
> - $(form.elements[i]).next('.required_param').remove();
> - }
> - }
> - }
> -
> - if (val !== '') {
> - if (!edit) {
> - val = val.replace(/"/g, '\\"'); // escape double quotes
> - }
> - params.push(param + '="' + val + '"');
> - }
> - }
> -
> - if (emptyRequiredParam) {
> - return false;
> - }
> -
> - var blob, pluginContentTextarea = $("[name=content]", form),
> - pluginContentTextareaEditor = syntaxHighlighter.get(pluginContentTextarea);
> - var cont = (pluginContentTextareaEditor ? pluginContentTextareaEditor.getValue() : pluginContentTextarea.val());
> -
> - if (meta.body) {
> - blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' + cont + '{' + type.toUpperCase() + '}';
> - } else {
> - blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}';
> - }
> -
> - if (edit) {
> - container.children('form').submit();
> - // quick and dirty reload
> - window.location = window.location.href;
> - } else {
> - insertAt(area_id, blob, false, false, replaceText);
> - }
> - $modal.modal("hide");
> -
> - return false;
> - });
> -
> - var heading = container.find('h3').hide();
> -
> var $modal = $('.modal.fade:not(.in)').first();
>
> - $modal.find(".modal-dialog").empty()
> - .append($("<div>").addClass("modal-content")
> - .append($("<div>").addClass("modal-header").append($("<h4>").addClass("modal-title").text(heading.text())))
> - .append($("<div>").addClass("modal-body").append(container))
> - .append($("<div>").addClass("modal-footer").append($closeBtn, $submitBtn))
> - );
> + var url = $.service("plugin", "edit", {
> + area_id: area_id,
> + type: type,
> + index: index,
> + page: pageName,
> + pluginArgs: pluginArgs,
> + bodyContent: bodyContent,
> + edit_icon: edit_icon,
> + selectedMod: selectedMod ? selectedMod : "",
> + modal: 1
> + });
>
> // Make the form appear
> - $modal.modal({
> - show: false // if it;'s the first time the show.bs.modal doesn't trigger sometimes
> - })
> - .one('show.bs.modal', function () { // Bind open event
> + $modal
> + .modal({
> + remote: url,
> + show: false // if it's the first time the show.bs.modal doesn't trigger sometimes
> + })
> + .one('loaded.bs.modal', function () { // Bind remote loaded event
> handlePluginFieldsHierarchy(type);
> + handleFormSubmit(this, type, edit_icon, area_id, replaceText);
> })
> .modal("show");
>
> @@ -231,7 +124,7 @@
> arguments: arguments,
> modal: $modal
> });
> - }
> + };
>
> /*
> * Hides all children fields in a wiki-plugin form and
> @@ -240,14 +133,15 @@
> */
> function handlePluginFieldsHierarchy(type) {
> var pluginParams = tiki_plugins[type]['params'];
> + var $container = $('#plugin_params');
>
> var parents = {};
>
> $.each(pluginParams, function (paramName, paramValues) {
> if (paramValues.parent) {
> - var $parent = $('[name$="params[' + paramValues.parent.name + ']"]', '.wikiplugin_edit');
> + var $parent = $('[name$="params[' + paramValues.parent.name + ']"]', $container);
>
> - var $row = $('.wikiplugin_edit').find('#param_' + paramName);
> + var $row = $container.find('#param_' + paramName);
> $row.addClass('parent_' + paramValues.parent.name + '_' + paramValues.parent.value);
>
> if ($parent.val() !== paramValues.parent.value) {
> @@ -271,14 +165,69 @@
> $.each(parents, function (parentName, parent) {
> parent.parentElement.change(function () {
> $.each(parent.children, function () {
> - $('.wikiplugin_edit #param_' + this).hide();
> + $container.find('#param_' + this).hide();
> });
> - $('.wikiplugin_edit .parent_' + parentName + '_' + this.value).show();
> + $container.find('.parent_' + parentName + '_' + this.value).show();
> })
> .change().trigger("chosen:updated");
> });
> }
>
> + /**
> + * set up insert/replace button and submit handler in "textarea" edit mode
> + *
> + * @param container
> + * @param type
> + * @param edit_icon
> + * @param area_id
> + */
> + function handleFormSubmit(container, type, edit_icon, area_id, replaceText) {
> +
> + var meta = tiki_plugins[type], params = [], edit = !!edit_icon, emptyRequiredParam = false;
> +
> + var $form = $("form", container);
> +
> + $form.submit(function () {
> +
> + if (!process_submit(this)) {
> + return false;
> + }
> +
> + $(".form-control", $form).each(function () {
> +
> + var matches = $(this).attr("name").match(/params\[(.*)\]/),
> + val = $(this).val();
> +
> + if (!matches) {
> + // it's not a parameter, skip
> + return;
> + }
> +
> + if (val&& !edit) {
> + val = val.replace(/"/g, '\\"'); // escape double quotes
> + params.push(matches[1] + '="' + val + '"');
> + }
> + });
> +
> + var blob, pluginContentTextarea = $("[name=content]", $form),
> + pluginContentTextareaEditor = syntaxHighlighter.get(pluginContentTextarea),
> + cont = (pluginContentTextareaEditor ? pluginContentTextareaEditor.getValue() : pluginContentTextarea.val());
> +
> + if (!edit) {
> + if (meta.body) {
> + blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' + cont + '{' + type.toUpperCase() + '}';
> + } else {
> + blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}';
> + }
> +
> + insertAt(area_id, blob, false, false, replaceText);
> + $(container).modal("hide");
> +
> + return false;
> + }
> + });
> + }
> +
> function dialogSelectElement(area_id, elementStart, elementEnd) {
> if (typeof CKEDITOR !== 'undefined' && typeof CKEDITOR.instances[area_id] !== 'undefined') {
> return;
> @@ -317,325 +266,4 @@
>
> }
>
> -
> - function build_plugin_form(type, index, pageName, pluginArgs, bodyContent, selectedMod) {
> - var form = document.createElement('form');
> - form.method = 'post';
> - form.action = 'tiki-wikiplugin_edit.php';
> - form.className = 'wikiplugin_edit';
> -
> - var hiddenPage = document.createElement('input');
> - hiddenPage.type = 'hidden';
> - hiddenPage.name = 'page';
> - hiddenPage.value = pageName;
> - form.appendChild(hiddenPage);
> -
> - var hiddenType = document.createElement('input');
> - hiddenType.type = 'hidden';
> - hiddenType.name = 'type';
> - hiddenType.value = type;
> - form.appendChild(hiddenType);
> -
> - var hiddenIndex = document.createElement('input');
> - hiddenIndex.type = 'hidden';
> - hiddenIndex.name = 'index';
> - hiddenIndex.value = index;
> - form.appendChild(hiddenIndex);
> -
> - //
> - var savedArgs = document.createElement('input');
> - savedArgs.type = 'hidden';
> - savedArgs.name = 'args';
> - savedArgs.value = $.toJSON(pluginArgs);
> - form.appendChild(savedArgs);
> -
> - //Convert to JSON and then back to an object to break
> - //link between meta local variable and tiki_plugins[type] global variable.
> - //Otherwise each change to meta.params using the extend below was being appended to the global
> - //Probably a much easier way to do this
> - var infostring = $.toJSON(tiki_plugins[type]);
> - var meta = $.parseJSON(infostring);
> -
> - //For PluginModule, add selected module parameters to the plugin edit form
> - if (type == 'module') {
> - //isolate the module parameter object so it will be shown first in the form
> - var onlymod = {"params": {"module": meta.params.module}};
> - //user has not changed the module selection since opening the form
> - if (typeof selectedMod == 'undefined') {
> - //pick up the parameters of the saved module parameter
> - if (typeof pluginArgs.module != 'undefined') {
> - //this orders the module parameter first, module related parameters second, other PluginModule parameters besides module last
> - meta.params = $.extend(onlymod.params, tiki_module_params[pluginArgs.module].params, meta.params);
> - //Use the module description
> - meta.params.module.description = tiki_module_params[pluginArgs.module].description;
> - //otherwise pick up the parameters of the first module option since that will be selected automatically
> - } else {
> - meta.params = $.extend(onlymod.params, tiki_module_params[meta.params.module.options[0].value].params, meta.params);
> - meta.params.module.description = tiki_module_params[meta.params.module.options[0].value].description;
> - }
> - //user has selected another module while the form was open - pick up parameters for the selected module
> - } else if (tiki_module_params[selectedMod] != null) {
> - meta.params = $.extend(onlymod.params, tiki_module_params[selectedMod].params, meta.params);
> - meta.params.module.description = tiki_module_params[selectedMod].description;
> - }
> - }
> -
> - var header = document.createElement('h3');
> - header.innerHTML = meta.name;
> - form.appendChild(header);
> -
> - var desc = document.createElement('div');
> - desc.innerHTML = meta.description;
> - if (meta.documentation && jqueryTiki.helpurl) {
> - desc.innerHTML += ' <a href="' + jqueryTiki.helpurl + meta.documentation + '" target="tikihelp" class="tikihelp" tabIndex="-1" title="' + tr('Help') + '">' +
> - '<span class="icon icon-help fa fa-question-circle fa-fw"></span>' +
> - '</a>';
> -
> - }
> - form.appendChild(desc);
> -
> - var table = document.createElement('table'), param;
> - table.className = 'table';
> - table.id = 'plugin_params';
> - form.appendChild(table);
> -
> - for (param in meta.params) {
> - if (meta.params[param].advanced) {
> - var br = document.createElement('br');
> - form.appendChild(br);
> -
> - var span_advanced_button = document.createElement('span');
> - span_advanced_button.className = 'button';
> - form.appendChild(span_advanced_button);
> -
> - var advanced_button = document.createElement('a');
> - advanced_button.innerHTML = tr('Advanced options');
> - advanced_button.onclick = function () {
> - flip('plugin_params_advanced');
> - };
> - span_advanced_button.appendChild(advanced_button);
> -
> - var table_advanced = document.createElement('table');
> - table_advanced.className = 'normal';
> - table_advanced.style.display = 'none';
> - table_advanced.id = 'plugin_params_advanced';
> - form.appendChild(table_advanced);
> -
> - break;
> - }
> - }
> -
> - var potentiallyExtraPluginArgs = pluginArgs, extraArg;
> -
> - var rowNumber = 0;
> - var rowNumberAdvanced = 0;
> - for (param in meta.params) {
> - if (typeof(meta.params[param]) != 'object' || meta.params[param].name == 'array') {
> - continue;
> - }
> -
> - var row;
> - if (meta.params[param].advanced && !meta.params[param].required && typeof pluginArgs[param] === "undefined") {
> - row = table_advanced.insertRow(rowNumberAdvanced++);
> - } else {
> - row = table.insertRow(rowNumber++);
> - }
> - var value = pluginArgs.length < 1 ? '' : pluginArgs[param];// for param like sort
> - //for use with PluginModule to identify saved module parameter value
> - var nsavedArgs = $.parseJSON($(form).find('input[name="args"][type="hidden"]').val());
> - //last two parameters (selectedMod and savedArgs are only needed for PluginModule
> - build_plugin_form_row(row, param, meta.params[param].name, meta.params[param].required, value, meta.params[param].description, meta.params[param], selectedMod, nsavedArgs);
> -
> - delete potentiallyExtraPluginArgs[param];
> - }
> -
> - for (extraArg in potentiallyExtraPluginArgs) {
> - if (extraArg === '') {
> - // TODO HACK: See bug 2499 http://dev.tiki.org/tiki-view_tracker_item.php?itemId=2499
> - continue;
> - }
> -
> - row = table.insertRow(rowNumber++);
> - build_plugin_form_row(row, extraArg, extraArg, 'extra', pluginArgs[extraArg], extraArg);
> - }
> -
> - var bodyRow = table.insertRow(rowNumber++);
> - var bodyCell = bodyRow.insertCell(0);
> - var bodyField = document.createElement('textarea');
> - bodyField.rows = '12';
> - bodyField.className = 'form-control';
> - var bodyDesc = document.createElement('div');
> -
> - if (meta.body) {
> - bodyDesc.innerHTML = meta.body;
> - } else {
> - bodyRow.style.display = 'none';
> - }
> - bodyField.name = 'content';
> - bodyField.value = bodyContent;
> -
> - bodyRow.className = 'formcolor';
> -
> - bodyCell.appendChild(bodyDesc);
> - bodyCell.appendChild(bodyField);
> - bodyCell.colSpan = '2';
> -
> - var submitRow = table.insertRow(rowNumber++);
> - var submitCell = submitRow.insertCell(0);
> - var submit = document.createElement('input');
> -
> - submit.type = 'submit';
> - submitCell.colSpan = 2;
> - submitCell.appendChild(submit);
> - submitCell.className = 'submit';
> -
> - return form;
> - }
> -
> -//last two parameters (selectedMod and savedArgs are only needed for PluginModule
> - function build_plugin_form_row(row, name, label_name, requiredOrSpecial, value, description, paramDef, selectedMod, savedArgs) {
> -
> - var label = row.insertCell(0);
> - var field = row.insertCell(1);
> - row.className = 'form-group';
> - row.id = 'param_' + name;
> -
> - label.innerHTML = label_name;
> - label.className = 'col-sm-3';
> - field.className = 'col-sm-9';
> - switch (requiredOrSpecial) {
> - case (true):  // required flag
> - label.style.fontWeight = 'bold';
> - break;
> - case ('extra') :
> - label.style.fontStyle = 'italic';
> - }
> -
> - var input, icon;
> - if (paramDef && paramDef.options) {
> - input = document.createElement('select');
> - input.name = 'params[' + name + ']';
> - input.className = 'form-control';
> - for (var o = 0; o < paramDef.options.length; o++) {
> - var opt = document.createElement('option');
> - opt.value = paramDef.options[o].value;
> - var opt_text = document.createTextNode(paramDef.options[o].text);
> - opt.appendChild(opt_text);
> - //either not PluginModule or user has not changed module selection, so use saved value
> - if (typeof selectedMod == 'undefined') {
> - if (value && opt.value == value) {
> - opt.selected = true;
> - }
> - } else {
> - //user changed module selection in PluginModule
> - if (selectedMod == opt.value) {
> - opt.selected = true;
> - } else if (savedArgs.module == opt.value) {
> - //use later to display saved module parameter value
> - var savedtext = opt.innerHTML;
> - opt.style.fontWeight = 'bold';
> - opt.innerHTML = opt.innerHTML + '  -- ' + tr('saved value');
> - }
> - }
> - input.appendChild(opt);
> - }
> - } else {
> - input = document.createElement('input');
> - input.className = 'form-control';
> - input.type = 'text';
> - input.name = 'params[' + name + ']';
> - if (value) {
> - input.value = value.replace(/\\"/g, '"'); // unescape quotes
> - }
> - }
> -
> - field.appendChild(input);
> - if (paramDef && paramDef.type == 'image') {
> - icon = document.createElement('img');
> - icon.src = 'img/icons/image.png';
> - input.id = paramDef.area ? paramDef.area : 'fgal_picker';
> - icon.onclick = function () {
> - openFgalsWindowArea(paramDef.area ? paramDef.area : 'fgal_picker');
> - };
> - field.appendChild(icon);
> - } else if (paramDef && paramDef.type == 'fileId') {
> - var help = document.createElement('span');
> - input.id = paramDef.area ? paramDef.area : 'fgal_picker';
> - help.onclick = function () {
> - openFgalsWindowArea(paramDef.area ? paramDef.area : 'fgal_picker');
> - };
> - help.innerHTML = " <a href='#'>" + tr('Pick a file.') + "</a>";
> - field.appendChild(help);
> - } else if (paramDef && paramDef.type == 'kaltura') {
> - input.id = paramDef.area;
> - var img = $("<img />")
> - .attr("src", paramDef.icon)
> - .addClass("icon")
> - .css("cursor", "pointer")
> - .attr("title", tr("Upload or record media"))
> - ;
> - $(field).append(
> - $('<a/>')
> - .attr('href', $.service('kaltura', 'upload'))
> - .append(img)
> - .click(function () {
> - $(this).serviceDialog({
> - title: tr("Upload or record media"),
> - width: 710,
> - height: 450,
> - hideButtons: true,
> - success: function (data) {
> - if (data.entries) {
> - input.value = data.entries[0];
> - }
> - }
> - });
> - return false;
> - })
> - );
> - }
> -
> - if (description) {
> - var desc = document.createElement('div');
> - desc.style.fontSize = 'x-small';
> - desc.innerHTML = description;
> - field.appendChild(desc);
> - }
> - if (paramDef && paramDef.accepted) {
> - $(field).append(
> - $("<div>")
> - .css("fontSize", "x-small")
> - .html("<strong>" + tr("Accepted:") + "</strong><br>" + paramDef.accepted)[0]
> - );
> - }
> - //in PluginModule, show saved nodule parameter value if user has changed selection
> - //since the form changes to match the newly selected module, it's useful to show the
> - //saved module parameter so the user can go back to it
> - if (typeof savedtext != 'undefined') {
> - var saved = document.createElement('div');
> - saved.style.fontSize = 'x-small';
> - saved.style.fontStyle = 'italic';
> - saved.style.fontWeight = 'bold';
> - saved.innerHTML = tr('Saved value:') + ' ' + savedtext;
> - field.appendChild(saved);
> - }
> -
> - if (paramDef && paramDef.filter) {
> - if (paramDef.filter == "pagename") {
> - $(input).tiki("autocomplete", "pagename");
> - } else if (paramDef.filter == "groupname") {
> - $(input).tiki("autocomplete", "groupname", {multiple: true, multipleSeparator: "|"});
> - } else if (paramDef.filter == "username") {
> - $(input).tiki("autocomplete", "username", {multiple: true, multipleSeparator: "|"});
> - } else if (paramDef.filter == "date") {
> - $(input).tiki("datepicker");
> - }
> - }
> -
> - }
> -
> - function openFgalsWindowArea(area) {
> - openFgalsWindow('tiki-list_file_gallery.php?filegals_manager=' + area + '&galleryId=' + jqueryTiki.home_file_gallery, true); // reload
> - }
> -
> })(jQuery);
>
> Copied: trunk/templates/plugin/edit.tpl (from rev 61597, trunk/templates/plugin/list.tpl)
> ===================================================================
> --- trunk/templates/plugin/edit.tpl                        (rev 0)
> +++ trunk/templates/plugin/edit.tpl 2017-03-13 14:58:28 UTC (rev 61664)
> @@ -0,0 +1,116 @@
> +{extends 'layout_view.tpl'}
> +
> +{block name="title"}
> + <h3>{$title}</h3>
> +{/block}
> +
> +{block name="content"}
> + {function plugin_edit_row}{* needs to be in the same block it seems? *}
> + {if $param.area}{$inputId=$param.area|escape}{else}{$inputId="param_{$name|escape}_input"}{/if}
> + <div  class="col-sm-3">
> + <label for="{$inputId}">{$param.name|escape}</label>
> + {if not empty($param.type)}
> + {$onclick = "openFgalsWindow('{$prefs.home_file_gallery|sefurl:'file gallery':true}filegals_manager={$param.area|escape}&id=1', true);return false;"}
> + {if $param.type eq 'image'}
> + <br>{icon name='image' title='{tr}Select image{/tr}' onclick=$onclick class='btn btn-xs btn-default'}
> + {elseif $param.type eq 'fileId'}
> + <br>{icon name='file' title='{tr}Pick a file{/tr}' onclick=$onclick class='btn btn-xs btn-default'}
> + {elseif $param.type eq 'kaltura'}
> + {jq}
> +$("#picker_{{$name|escape}}").parent().click(function () {
> + $(this).serviceDialog({
> + title: tr("Upload or record media"),
> + width: 710,
> + height: 450,
> + hideButtons: true,
> + success: function (data) {
> + if (data.entries) {
> + input.value = data.entries[0];
> + }
> + }
> + });
> + return false;
> +});
> + {/jq}
> + <br>{icon name='video' title='{tr}Upload or record media{/tr}' href={service controller='kaltura' action='upload'} id='picker_'|cat:$name|escape class='btn btn-xs btn-default'}
> + {/if}
> + {/if}
> + </div>
> + <div class="col-sm-9">
> + {if (not empty($param.parent.name))}
> + {$groupClass = " group-`$param.parent.name`"}
> + {else}
> + {$groupClass = ''}
> + {/if}
> + {if empty($param.options)}
> + <input value="{if isset($pluginArgs[$name])}{$pluginArgs[$name]}{/if}" class="form-control{$groupClass}" id="{$inputId}" type="text" name="params[{$name|escape}]">
> + {if not empty($param.filter)}
> + {if $param.filter eq "pagename"}
> + {jq}$({{$inputId}}).tiki("autocomplete", "pagename");{/jq}
> + {elseif $param.filter eq "groupname"}
> + {jq}$({{$inputId}}).tiki("autocomplete", "groupname", {multiple: true, multipleSeparator: "|"});{/jq}
> + {elseif $param.filter eq "username"}
> + {jq}$({{$inputId}}).tiki("autocomplete", "username", {multiple: true, multipleSeparator: "|"});{/jq}
> + {elseif $param.filter eq "date"}
> + {jq}$({{$inputId}}).tiki("datepicker");{/jq}
> + {/if}
> + {/if}
> +
> + {else}
> + <select class="form-control{$groupClass}" type="text" name="params[{$name|escape}]" id="{$inputId}">
> + {foreach $param.options as $option}
> + <option value="{$option.value|escape}" {if isset($pluginArgs[$name]) and $pluginArgs[$name] eq $option.value} selected="selected"{/if}>
> + {$option.text|escape}
> + </option>
> + {/foreach}
> + </select>
> + {/if}
> + <div class="description">{$param.description}</div>
> + </div>
> + {/function}
> + <div class="form-horizontal" id="plugin_params">
> + <form action="{service controller='plugin' action='edit'}" method="post">
> + {foreach $info.params as $name => $param}
> + <div class="form-group{if $param.advanced} advanced{/if}" id="param_{$name|escape}">
> + {plugin_edit_row param=$param name=$name info=$info pluginArgs=$pluginArgs}
> + </div>
> + {/foreach}
> + {if not empty($info.advancedParams)}
> + {button _text='Advanced' _onclick="$('.form-group.advanced.default').toggle('fast'); return false;" _class='btn btn-xs margin-bottom-md'}
> + {foreach $info.advancedParams as $name => $param}
> + <div class="form-group advanced default" style="display: none;">
> + {plugin_edit_row param=$param name=$name info=$info pluginArgs=$pluginArgs}
> + </div>
> + {/foreach}
> + {/if}
> +
> + <div class="form-group"{if empty($info.body)} style="display:none"{/if}>
> + <label for="content" class="col-sm-3">{tr}Body{/tr}</label>
> + <div class="col-sm-9">
> + <textarea name="content" id="content" class="form-control">{$bodyContent|escape}</textarea>
> + <div class="description">{$info.body}</div>
> + </div>
> + </div>
> +
> + <div class="submit">
> + <input type="hidden" name="page" value="{$pageName}">
> + <input type="hidden" name="type" value="{$type}">
> + <input type="hidden" name="index" value="{$index}">
> + <input type="hidden" name="args" value="{$pluginArgsJSON}">
> + <input type="submit" class="btn btn-primary" value="{tr}Save{/tr}">
> + </div>
> +
> + {if $type eq 'module'}
> + {jq}$("#param_module_input").change(function () {
> + var selectMod = $(this).val();
> + $.closeModal();
> + $(document).one("hidden.bs.modal", function () {
> + popupPluginForm("{{$area_id}}","{{$type}}", {{$index}}, "{{$pageName}}", {{$pluginArgsJSON}}, "{{$bodyContent}}", "{{$edit_icon}}", selectMod);
> + });
> + });{/jq}
> + {/if}
> +
> + </form>
> + </div>
> +{/block}
> +
>
> Modified: trunk/tiki-wikiplugin_edit.php
> ===================================================================
> --- trunk/tiki-wikiplugin_edit.php 2017-03-13 12:09:36 UTC (rev 61663)
> +++ trunk/tiki-wikiplugin_edit.php 2017-03-13 14:58:28 UTC (rev 61664)
> @@ -10,62 +10,9 @@
>
> require 'tiki-setup.php';
>
> -if ( ! isset( $_POST['page'], $_POST['content'], $_POST['index'], $_POST['type'], $_SERVER['HTTP_REFERER'] ) )
> - die( 'Missing parameters' );
> +trigger_error(tr('Note, deprecated file tiki-wikiplugin_edit.php, code moved to service plugin->replace'));
>
> -$page = $_POST['page'];
> +TikiLib::lib('service')->render('plugin', 'replace', $jitPost);
>
> -$plugin = strtolower(basename($_POST['type']));
> -$type = TikiLib::strtoupper($plugin);
> -
> -if (empty($parserlib)) {
> - $parserlib = TikiLib::lib('parser');
> -}
> -
> -if ( ! $meta = $parserlib->plugin_info($plugin) )
> - exit;
> -
> -if ( ! isset( $_POST['message'] ) )
> - $_POST['message'] = (isset($meta['name']) ? tra($meta['name']) : $plugin) . ' ' . tra('Plugin modified by editor.');
> -
> -$info = $tikilib->get_page_info($page);
> -$tikilib->get_perm_object($page, 'wiki page', $info, true);
> -if ($tiki_p_edit != 'y') {
> - header("Location: {$_SERVER['HTTP_REFERER']}");
> - exit;
> -}
> -$content = $_POST['content'];
> -$current = $info['data'];
> -
> -$matches = WikiParser_PluginMatcher::match($current);
> -$count = 0;
> -foreach ( $matches as $match ) {
> - if ( $match->getName() !== $plugin ) {
> - continue;
> - }
> -
> - ++$count;
> -
> - if ( $_POST['index'] == $count ) {
> - //by using content of "~same~", it will not replace the body that is there
> - $content = ($content == "~same~" ? $match->getBody() : $content);
> - $params = $match->getArguments();
> -
> - // If parameters are provided, rebuild the parameter line
> - if ( isset( $_POST['params'] ) && is_array($_POST['params']) ) {
> - // $values was relaxed to accept any argument rather than those defined up front
> - // in the plugin's parameter list. This facilitates the use of modules as plugins.
> - $params = $_POST['params'];
> - }
> -
> - $match->replaceWithPlugin($plugin, $params, $content);
> -
> - $parsed = $matches->getText();
> -
> - $tikilib->update_page($page, $parsed, $_POST['message'], $user, $tikilib->get_ip_address());
> - break;
> - }
> -}
> -
> header("Location: {$_SERVER['HTTP_REFERER']}");
> exit;
>
> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
>
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Tikiwiki-cvs mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
>


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
TikiWiki-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]

lindon-4
Impressive work Jonny - many thanks for this great leap forward!

Taking a quick look I was wondering if it were possible for the popups to be any wider. If not, we’ll need to cut down on the help text in some places, which is probably a good idea anyway :) Also miss the scrollbar a little (but not much!). All in all, seems to be working very well and it’s may be just a matter of getting used to the things I mentioned rather than changing anything.

Thanks again - well done.
Regards,
lindon


> On Mar 13, 2017, at 11:11 AM, Jonny Bradley <[hidden email]> wrote:
>
> Hi all
>
> This is a quite big change for Tiki 17, and really quite overdue and needed for the list plugin GUI, which i'm hoping now to add before we branch (for which thank you Marc!)
>
> Plugin edit forms are now created sever-side so we can use a template (templates/plugin/edit.tpl) to build the form and all the goodness of a php service lib/core/Services/Edit/PluginController.php for processing it. Rather than re-creating the ancient custom js validation i've used the jquery validator (if the feature is enabled) which i think works better and will be more useful in the future.
>
> In the future we should be able to extend this method for editing plugins to other objects, not just wiki pages.
>
> Anyway, as with many of these big changes there isn't a huge amount to see that's new (yet) and something somewhere is bound to have borken so please do let me know if you find anything related to this that's fallen off!
>
> Thanks,
>
> jonny
>
>
>
>
>> On 13 Mar 2017, at 14:58, [hidden email] wrote:
>>
>> Revision: 61664
>>         http://sourceforge.net/p/tikiwiki/code/61664
>> Author:   jonnybradley
>> Date:     2017-03-13 14:58:28 +0000 (Mon, 13 Mar 2017)
>> Log Message:
>> -----------
>> [MOD] plugins: Move plugin edit form processing to a serverside AJAX service.
>> TODO Switch over remaining usages of tiki-wikiplugin_edit.php to service plugin replace and remove that and tiki*js.php files
>> Probably further tidying up and fixes to do too, please advice of any breakages (thanks marcalporte)
>>
>> Modified Paths:
>> --------------
>>   trunk/lib/core/Services/Edit/PluginController.php
>>   trunk/lib/jquery_tiki/tiki-pluginedit.js
>>   trunk/tiki-wikiplugin_edit.php
>>
>> Added Paths:
>> -----------
>>   trunk/templates/plugin/edit.tpl
>>
>> Modified: trunk/lib/core/Services/Edit/PluginController.php
>> ===================================================================
>> --- trunk/lib/core/Services/Edit/PluginController.php 2017-03-13 12:09:36 UTC (rev 61663)
>> +++ trunk/lib/core/Services/Edit/PluginController.php 2017-03-13 14:58:28 UTC (rev 61664)
>> @@ -17,7 +17,7 @@
>>
>> function __construct()
>> {
>> - $this->parserlib = TikiLib::lib('parser');
>> + $this->pluginList = [];
>> }
>>
>> function setUp()
>> @@ -27,7 +27,12 @@
>> $this->pluginList = TikiLib::lib('wiki')->list_plugins(true);
>> }
>>
>> -
>> + /**
>> + * List all or some of theplugins for the textarea control panel
>> + *
>> + * @param JitFilter $input
>> + * @return array
>> + */
>> function action_list($input)
>> {
>> $filter = $input->filter->text();
>> @@ -41,7 +46,7 @@
>> }
>> $results = TikiLib::lib('prefs')->getMatchingPreferences($query);
>>
>> - foreach($results as $result) {
>> + foreach ($results as $result) {
>> if (strpos($result, 'wikiplugin_') === 0) {
>> $key = strtoupper(substr($result, 11));
>> $arr = array_filter($this->pluginList, function ($plugin) use ($key) {
>> @@ -72,6 +77,214 @@
>> );
>> }
>>
>> + /**
>> + * Display plugin edit form or process saving changes
>> + *
>> + * @param JitFilter $input
>> + * @return array
>> + * @throws Services_Exception_BadRequest
>> + * @throws Services_Exception_Denied
>> + */
>> + function action_edit($input)
>> + {
>> + global $prefs;
>> +
>> + $parserlib = TikiLib::lib('parser');
>> +
>> + $area_id = $input->area_id->alnumdash();
>> + $type = $input->type->word();
>> + $index = $input->index->int();
>> + $page = $input->page->pagename();
>> + $pluginArgs = $input->pluginArgs->array();
>> + $bodyContent = $input->bodyContent->wikicontent();
>> + $edit_icon = $input->edit_icon->text();
>> + $selectedMod = $input->selectedMod->text();
>> +
>> + $tikilib = TikiLib::lib('tiki');
>> + $pageInfo = $tikilib->get_page_info($page);
>> + if (! $pageInfo) {
>> + // in edit mode
>> + } else {
>> + $perms = $tikilib->get_perm_object($page, 'wiki page', $pageInfo, false);
>> + if ($perms['tiki_p_edit'] !== 'y') {
>> + throw new Services_Exception_Denied(tr('You do not have permission to edit "%0"', $page));
>> + }
>> + }
>> +
>> +
>> + if ($_SERVER['REQUEST_METHOD'] === 'POST') {
>> +
>> + $this->action_replace($input);
>> +
>> + return [
>> + 'redirect' => TikiLib::lib('wiki')->sefurl($page),
>> + ];
>> +
>> + } else {        // render the form
>> +
>> + $info = $parserlib->plugin_info($type);
>> + $info['advancedParams'] = [];
>> + $validationRules = [];
>> +
>> + foreach ($info['params'] as $key => $param) {
>> + if ($prefs['feature_jquery_validation'] === 'y') {
>> + // $("#insertItemForm4").validate({rules: { ins_11: { required: true}, ins_13: { remote: { url: "validate-ajax.php", type: "post", data: { validator: "distinct", parameter: "trackerId=4&fieldId=13&itemId=0", message: "", input: function() { return $("#ins_13").val(); } } } }, ins_18: { required: true, remote: { url: "validate-ajax.php", type: "post", data: { validator: "distinct", parameter: "trackerId=4&fieldId=18&itemId=0", message: "this is not distinct!", input: function() { return $("#ins_18").val(); } } } }}, messages: { ins_11: { required: "This field is required" }, ins_18: { required: "this is not distinct!" }},
>> + if ($param['required']) {
>> + if (empty($param['parent'])) {
>> + $validationRules["params[$key]"] = ['required' => true];
>> + } else {
>> + $validationRules["params[$key]"] = ['required_in_group' => [
>> + 1,
>> + '.group-' . $param['parent']['name'],
>> + 'other',
>> + ]];
>> + }
>> + }
>> + }
>> + if (! empty($param['advanced']) && ! isset($pluginArgs[$key]) && empty($param['parent'])) {
>> + $info['advancedParams'][$key] = $param;
>> + unset($info['params'][$key]);
>> + }
>> + }
>> +
>> + if ($validationRules) {
>> + $rules = json_encode(['rules' => $validationRules]);
>> + TikiLib::lib('header')->add_jq_onready('$("#plugin_params > form").validate(' . $rules . ');');
>> + }
>> +
>> + if ($type === 'module' && isset($pluginArgs['module'])) {
>> + if ($selectedMod) {
>> + $pluginArgs['module'] = $selectedMod;
>> + }
>> + $file = 'modules/mod-func-' . $pluginArgs['module'] . '.php';
>> + if (file_exists($file)) {
>> + include_once($file);
>> + $info_func = "module_{$pluginArgs['module']}_info";
>> + if (function_exists($info_func)) {
>> + $moduleInfo = $info_func();
>> + if (isset($info['params']['max'])) {
>> + $max = $info['params']['max'];
>> + unset($info['params']['max']); // move "max" to last
>> + }
>> + foreach($moduleInfo['params'] as $key => $value) {
>> + $info['params'][$key] = $value;
>> + }
>> + if (! empty($max)) {
>> + $info['params']['max'] = $max;
>> + }
>> + // replace the module plugin description with the one from the select module
>> + $info['params']['module']['description'] = $moduleInfo['description'];
>> + }
>> +
>> + }
>> + }
>> +
>> + return [
>> + // pass back the input parameters
>> + 'area_id' => $area_id,
>> + 'type' => $type,
>> + 'index' => $index,
>> + 'pageName' => $page,
>> + 'pluginArgs' => $pluginArgs,
>> + 'pluginArgsJSON' => json_encode($pluginArgs),
>> + 'bodyContent' => $bodyContent,
>> + 'edit_icon' => $edit_icon,
>> + 'selectedMod' => $selectedMod,
>> +
>> + 'info' => $info,
>> + 'title' => $type,
>> + ];
>> + }
>> + }
>> +
>> + /**
>> + * Replace plugin in wiki content
>> + * Migrated from tiki-wikiplugin_edit.php
>> + *
>> + * @param JitFilter $input
>> + * @return array
>> + * @throws Services_Exception
>> + * @throws Services_Exception_BadRequest
>> + * @throws Services_Exception_Denied
>> + */
>> + function action_replace($input)
>> + {
>> + global $user;
>> +
>> + $tikilib = TikiLib::lib('tiki');
>> + $parserlib = TikiLib::lib('parser');
>> +
>> + $page = $input->page->pagename();
>> + $type = $input->type->word();
>> + $message = $input->message->text();
>> + $content = $input->content->wikicontent();
>> + $index = $input->index->int();
>> + $params = $input->params->array();
>> +
>> + $referer = $_SERVER['HTTP_REFERER'];
>> +
>> + if (! $page || ! $type || ! $referer || $_SERVER['REQUEST_METHOD'] !== 'POST') {
>> + throw new Services_Exception(tr('Missing parameters'));
>> + }
>> +
>> + $plugin = strtolower($type);
>> + $meta = $parserlib->plugin_info($plugin);
>> +
>> + if (! $page || ! $type || ! $referer) {
>> + throw new Services_Exception(tr('Plugin "%0" not found', $plugin));
>> + }
>> +
>> + if (! $message) {
>> + $message = tr('%0 Plugin modified by editor.', $plugin);
>> + }
>> +
>> + $info = $tikilib->get_page_info($page);
>> + if (! $info) {
>> + throw new Services_Exception_BadRequest(tr('Page "%0" not found', $page));
>> + }
>> +
>> + $perms = $tikilib->get_perm_object($page, 'wiki page', $info, false);
>> + if ($perms['tiki_p_edit'] !== 'y') {
>> + throw new Services_Exception_Denied(tr('You do not have permission to edit "%0"', $page));
>> + }
>> +
>> + $current = $info['data'];
>> +
>> + $matches = WikiParser_PluginMatcher::match($current);
>> + $count = 0;
>> + foreach ($matches as $match) {
>> + if ($match->getName() !== $plugin) {
>> + continue;
>> + }
>> +
>> + ++$count;
>> +
>> + if ($index === $count) {
>> + // by using content of "~same~", it will not replace the body that is there
>> + $content = ($content == "~same~" ? $match->getBody() : $content);
>> +
>> + if (! $params) {
>> + $params = $match->getArguments();
>> + }
>> +
>> + $match->replaceWithPlugin($plugin, $params, $content);
>> +
>> + $tikilib->update_page(
>> + $page,
>> + $matches->getText(),
>> + $message,
>> + $user,
>> + $tikilib->get_ip_address()
>> + );
>> +
>> + break;
>> + }
>> + }
>> +
>> + return [];
>> +
>> + }
>> +
>> }
>>
>>
>>
>> Modified: trunk/lib/jquery_tiki/tiki-pluginedit.js
>> ===================================================================
>> --- trunk/lib/jquery_tiki/tiki-pluginedit.js 2017-03-13 12:09:36 UTC (rev 61663)
>> +++ trunk/lib/jquery_tiki/tiki-pluginedit.js 2017-03-13 14:58:28 UTC (rev 61664)
>> @@ -82,137 +82,30 @@
>> replaceText = false;
>> }
>> }
>> - var form = build_plugin_form(type, index, pageName, pluginArgs, bodyContent, selectedMod);
>>
>> - //with PluginModule, if the user selects another module while the edit form is open
>> - //replace the form with a new one with fields to match the parameters for the module selected
>> - $(form).find('tr select[name="params[module]"]').change(function () {
>> - var npluginArgs = $.parseJSON($(form).find('input[name="args"][type="hidden"]').val());
>> - //this is the newly selected module
>> - var selectedMod = $(form).find('tr select[name="params[module]"]').val();
>> - $('div.plugin input[name="type"][value="' + type + '"]').parent().parent().remove();
>> - popupPluginForm(area_id, type, index, pageName, npluginArgs, bodyContent, edit_icon, selectedMod);
>> - });
>> - var $form = $(form).find('tr input[type=submit]').remove();
>> -
>> - container.append(form);
>> -
>> -
>> - var pfc = container.find('table tr').length; // number of rows (plugin form contents)
>> - var t = container.find('textarea:visible').length;
>> - if (t) {
>> - pfc += t * 3;
>> - }
>> - if (pfc > 9) {
>> - pfc = 9;
>> - }
>> - if (pfc < 2) {
>> - pfc = 2;
>> - }
>> - pfc = pfc / 10; // factor to scale dialog height
>> -
>> - var $closeBtn = $('<button>')
>> - .text(tr("Close"))
>> - .addClass('btn btn-default')
>> - .click(function () {
>> - $(this).parents(".modal").modal("hide");
>> - });
>> -
>> - var $submitBtn = $('<button>')
>> - .text(replaceText ? tr("Replace") : edit_icon ? tr("Submit") : tr("Insert"))
>> - .addClass('btn btn-primary')
>> - .click(function () {
>> -
>> - $(this).off("click").css("opacity", 0.3);
>> -
>> - var meta = tiki_plugins[type];
>> - var params = [];
>> - var edit = edit_icon;
>> - // whether empty required params exist or not
>> - var emptyRequiredParam = false;
>> -
>> - for (var i = 0; i < form.elements.length; i++) {
>> - var element = form.elements[i].name;
>> -
>> - var matches = element.match(/params\[(.*)\]/);
>> -
>> - if (matches === null) {
>> - // it's not a parameter, skip
>> - continue;
>> - }
>> - var param = matches[1];
>> -
>> - var val = form.elements[i].value;
>> -
>> - // check if fields that are required and visible are not empty
>> - if (meta.params[param]) {
>> - if (meta.params[param].required) {
>> - if (val === '' && $(form.elements[i]).is(':visible')) {
>> - $(form.elements[i]).css('border-color', 'red');
>> - if ($(form.elements[i]).next('.required_param').length === 0) {
>> - $(form.elements[i]).after('<div class="required_param" style="font-size: x-small; color: red;">(required)</div>');
>> - }
>> - emptyRequiredParam = true;
>> - }
>> - else {
>> - // remove required feedback if present
>> - $(form.elements[i]).css('border-color', '');
>> - $(form.elements[i]).next('.required_param').remove();
>> - }
>> - }
>> - }
>> -
>> - if (val !== '') {
>> - if (!edit) {
>> - val = val.replace(/"/g, '\\"'); // escape double quotes
>> - }
>> - params.push(param + '="' + val + '"');
>> - }
>> - }
>> -
>> - if (emptyRequiredParam) {
>> - return false;
>> - }
>> -
>> - var blob, pluginContentTextarea = $("[name=content]", form),
>> - pluginContentTextareaEditor = syntaxHighlighter.get(pluginContentTextarea);
>> - var cont = (pluginContentTextareaEditor ? pluginContentTextareaEditor.getValue() : pluginContentTextarea.val());
>> -
>> - if (meta.body) {
>> - blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' + cont + '{' + type.toUpperCase() + '}';
>> - } else {
>> - blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}';
>> - }
>> -
>> - if (edit) {
>> - container.children('form').submit();
>> - // quick and dirty reload
>> - window.location = window.location.href;
>> - } else {
>> - insertAt(area_id, blob, false, false, replaceText);
>> - }
>> - $modal.modal("hide");
>> -
>> - return false;
>> - });
>> -
>> - var heading = container.find('h3').hide();
>> -
>> var $modal = $('.modal.fade:not(.in)').first();
>>
>> - $modal.find(".modal-dialog").empty()
>> - .append($("<div>").addClass("modal-content")
>> - .append($("<div>").addClass("modal-header").append($("<h4>").addClass("modal-title").text(heading.text())))
>> - .append($("<div>").addClass("modal-body").append(container))
>> - .append($("<div>").addClass("modal-footer").append($closeBtn, $submitBtn))
>> - );
>> + var url = $.service("plugin", "edit", {
>> + area_id: area_id,
>> + type: type,
>> + index: index,
>> + page: pageName,
>> + pluginArgs: pluginArgs,
>> + bodyContent: bodyContent,
>> + edit_icon: edit_icon,
>> + selectedMod: selectedMod ? selectedMod : "",
>> + modal: 1
>> + });
>>
>> // Make the form appear
>> - $modal.modal({
>> - show: false // if it;'s the first time the show.bs.modal doesn't trigger sometimes
>> - })
>> - .one('show.bs.modal', function () { // Bind open event
>> + $modal
>> + .modal({
>> + remote: url,
>> + show: false // if it's the first time the show.bs.modal doesn't trigger sometimes
>> + })
>> + .one('loaded.bs.modal', function () { // Bind remote loaded event
>> handlePluginFieldsHierarchy(type);
>> + handleFormSubmit(this, type, edit_icon, area_id, replaceText);
>> })
>> .modal("show");
>>
>> @@ -231,7 +124,7 @@
>> arguments: arguments,
>> modal: $modal
>> });
>> - }
>> + };
>>
>> /*
>> * Hides all children fields in a wiki-plugin form and
>> @@ -240,14 +133,15 @@
>> */
>> function handlePluginFieldsHierarchy(type) {
>> var pluginParams = tiki_plugins[type]['params'];
>> + var $container = $('#plugin_params');
>>
>> var parents = {};
>>
>> $.each(pluginParams, function (paramName, paramValues) {
>> if (paramValues.parent) {
>> - var $parent = $('[name$="params[' + paramValues.parent.name + ']"]', '.wikiplugin_edit');
>> + var $parent = $('[name$="params[' + paramValues.parent.name + ']"]', $container);
>>
>> - var $row = $('.wikiplugin_edit').find('#param_' + paramName);
>> + var $row = $container.find('#param_' + paramName);
>> $row.addClass('parent_' + paramValues.parent.name + '_' + paramValues.parent.value);
>>
>> if ($parent.val() !== paramValues.parent.value) {
>> @@ -271,14 +165,69 @@
>> $.each(parents, function (parentName, parent) {
>> parent.parentElement.change(function () {
>> $.each(parent.children, function () {
>> - $('.wikiplugin_edit #param_' + this).hide();
>> + $container.find('#param_' + this).hide();
>> });
>> - $('.wikiplugin_edit .parent_' + parentName + '_' + this.value).show();
>> + $container.find('.parent_' + parentName + '_' + this.value).show();
>> })
>> .change().trigger("chosen:updated");
>> });
>> }
>>
>> + /**
>> + * set up insert/replace button and submit handler in "textarea" edit mode
>> + *
>> + * @param container
>> + * @param type
>> + * @param edit_icon
>> + * @param area_id
>> + */
>> + function handleFormSubmit(container, type, edit_icon, area_id, replaceText) {
>> +
>> + var meta = tiki_plugins[type], params = [], edit = !!edit_icon, emptyRequiredParam = false;
>> +
>> + var $form = $("form", container);
>> +
>> + $form.submit(function () {
>> +
>> + if (!process_submit(this)) {
>> + return false;
>> + }
>> +
>> + $(".form-control", $form).each(function () {
>> +
>> + var matches = $(this).attr("name").match(/params\[(.*)\]/),
>> + val = $(this).val();
>> +
>> + if (!matches) {
>> + // it's not a parameter, skip
>> + return;
>> + }
>> +
>> + if (val&& !edit) {
>> + val = val.replace(/"/g, '\\"'); // escape double quotes
>> + params.push(matches[1] + '="' + val + '"');
>> + }
>> + });
>> +
>> + var blob, pluginContentTextarea = $("[name=content]", $form),
>> + pluginContentTextareaEditor = syntaxHighlighter.get(pluginContentTextarea),
>> + cont = (pluginContentTextareaEditor ? pluginContentTextareaEditor.getValue() : pluginContentTextarea.val());
>> +
>> + if (!edit) {
>> + if (meta.body) {
>> + blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' + cont + '{' + type.toUpperCase() + '}';
>> + } else {
>> + blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}';
>> + }
>> +
>> + insertAt(area_id, blob, false, false, replaceText);
>> + $(container).modal("hide");
>> +
>> + return false;
>> + }
>> + });
>> + }
>> +
>> function dialogSelectElement(area_id, elementStart, elementEnd) {
>> if (typeof CKEDITOR !== 'undefined' && typeof CKEDITOR.instances[area_id] !== 'undefined') {
>> return;
>> @@ -317,325 +266,4 @@
>>
>> }
>>
>> -
>> - function build_plugin_form(type, index, pageName, pluginArgs, bodyContent, selectedMod) {
>> - var form = document.createElement('form');
>> - form.method = 'post';
>> - form.action = 'tiki-wikiplugin_edit.php';
>> - form.className = 'wikiplugin_edit';
>> -
>> - var hiddenPage = document.createElement('input');
>> - hiddenPage.type = 'hidden';
>> - hiddenPage.name = 'page';
>> - hiddenPage.value = pageName;
>> - form.appendChild(hiddenPage);
>> -
>> - var hiddenType = document.createElement('input');
>> - hiddenType.type = 'hidden';
>> - hiddenType.name = 'type';
>> - hiddenType.value = type;
>> - form.appendChild(hiddenType);
>> -
>> - var hiddenIndex = document.createElement('input');
>> - hiddenIndex.type = 'hidden';
>> - hiddenIndex.name = 'index';
>> - hiddenIndex.value = index;
>> - form.appendChild(hiddenIndex);
>> -
>> - //
>> - var savedArgs = document.createElement('input');
>> - savedArgs.type = 'hidden';
>> - savedArgs.name = 'args';
>> - savedArgs.value = $.toJSON(pluginArgs);
>> - form.appendChild(savedArgs);
>> -
>> - //Convert to JSON and then back to an object to break
>> - //link between meta local variable and tiki_plugins[type] global variable.
>> - //Otherwise each change to meta.params using the extend below was being appended to the global
>> - //Probably a much easier way to do this
>> - var infostring = $.toJSON(tiki_plugins[type]);
>> - var meta = $.parseJSON(infostring);
>> -
>> - //For PluginModule, add selected module parameters to the plugin edit form
>> - if (type == 'module') {
>> - //isolate the module parameter object so it will be shown first in the form
>> - var onlymod = {"params": {"module": meta.params.module}};
>> - //user has not changed the module selection since opening the form
>> - if (typeof selectedMod == 'undefined') {
>> - //pick up the parameters of the saved module parameter
>> - if (typeof pluginArgs.module != 'undefined') {
>> - //this orders the module parameter first, module related parameters second, other PluginModule parameters besides module last
>> - meta.params = $.extend(onlymod.params, tiki_module_params[pluginArgs.module].params, meta.params);
>> - //Use the module description
>> - meta.params.module.description = tiki_module_params[pluginArgs.module].description;
>> - //otherwise pick up the parameters of the first module option since that will be selected automatically
>> - } else {
>> - meta.params = $.extend(onlymod.params, tiki_module_params[meta.params.module.options[0].value].params, meta.params);
>> - meta.params.module.description = tiki_module_params[meta.params.module.options[0].value].description;
>> - }
>> - //user has selected another module while the form was open - pick up parameters for the selected module
>> - } else if (tiki_module_params[selectedMod] != null) {
>> - meta.params = $.extend(onlymod.params, tiki_module_params[selectedMod].params, meta.params);
>> - meta.params.module.description = tiki_module_params[selectedMod].description;
>> - }
>> - }
>> -
>> - var header = document.createElement('h3');
>> - header.innerHTML = meta.name;
>> - form.appendChild(header);
>> -
>> - var desc = document.createElement('div');
>> - desc.innerHTML = meta.description;
>> - if (meta.documentation && jqueryTiki.helpurl) {
>> - desc.innerHTML += ' <a href="' + jqueryTiki.helpurl + meta.documentation + '" target="tikihelp" class="tikihelp" tabIndex="-1" title="' + tr('Help') + '">' +
>> - '<span class="icon icon-help fa fa-question-circle fa-fw"></span>' +
>> - '</a>';
>> -
>> - }
>> - form.appendChild(desc);
>> -
>> - var table = document.createElement('table'), param;
>> - table.className = 'table';
>> - table.id = 'plugin_params';
>> - form.appendChild(table);
>> -
>> - for (param in meta.params) {
>> - if (meta.params[param].advanced) {
>> - var br = document.createElement('br');
>> - form.appendChild(br);
>> -
>> - var span_advanced_button = document.createElement('span');
>> - span_advanced_button.className = 'button';
>> - form.appendChild(span_advanced_button);
>> -
>> - var advanced_button = document.createElement('a');
>> - advanced_button.innerHTML = tr('Advanced options');
>> - advanced_button.onclick = function () {
>> - flip('plugin_params_advanced');
>> - };
>> - span_advanced_button.appendChild(advanced_button);
>> -
>> - var table_advanced = document.createElement('table');
>> - table_advanced.className = 'normal';
>> - table_advanced.style.display = 'none';
>> - table_advanced.id = 'plugin_params_advanced';
>> - form.appendChild(table_advanced);
>> -
>> - break;
>> - }
>> - }
>> -
>> - var potentiallyExtraPluginArgs = pluginArgs, extraArg;
>> -
>> - var rowNumber = 0;
>> - var rowNumberAdvanced = 0;
>> - for (param in meta.params) {
>> - if (typeof(meta.params[param]) != 'object' || meta.params[param].name == 'array') {
>> - continue;
>> - }
>> -
>> - var row;
>> - if (meta.params[param].advanced && !meta.params[param].required && typeof pluginArgs[param] === "undefined") {
>> - row = table_advanced.insertRow(rowNumberAdvanced++);
>> - } else {
>> - row = table.insertRow(rowNumber++);
>> - }
>> - var value = pluginArgs.length < 1 ? '' : pluginArgs[param];// for param like sort
>> - //for use with PluginModule to identify saved module parameter value
>> - var nsavedArgs = $.parseJSON($(form).find('input[name="args"][type="hidden"]').val());
>> - //last two parameters (selectedMod and savedArgs are only needed for PluginModule
>> - build_plugin_form_row(row, param, meta.params[param].name, meta.params[param].required, value, meta.params[param].description, meta.params[param], selectedMod, nsavedArgs);
>> -
>> - delete potentiallyExtraPluginArgs[param];
>> - }
>> -
>> - for (extraArg in potentiallyExtraPluginArgs) {
>> - if (extraArg === '') {
>> - // TODO HACK: See bug 2499 http://dev.tiki.org/tiki-view_tracker_item.php?itemId=2499
>> - continue;
>> - }
>> -
>> - row = table.insertRow(rowNumber++);
>> - build_plugin_form_row(row, extraArg, extraArg, 'extra', pluginArgs[extraArg], extraArg);
>> - }
>> -
>> - var bodyRow = table.insertRow(rowNumber++);
>> - var bodyCell = bodyRow.insertCell(0);
>> - var bodyField = document.createElement('textarea');
>> - bodyField.rows = '12';
>> - bodyField.className = 'form-control';
>> - var bodyDesc = document.createElement('div');
>> -
>> - if (meta.body) {
>> - bodyDesc.innerHTML = meta.body;
>> - } else {
>> - bodyRow.style.display = 'none';
>> - }
>> - bodyField.name = 'content';
>> - bodyField.value = bodyContent;
>> -
>> - bodyRow.className = 'formcolor';
>> -
>> - bodyCell.appendChild(bodyDesc);
>> - bodyCell.appendChild(bodyField);
>> - bodyCell.colSpan = '2';
>> -
>> - var submitRow = table.insertRow(rowNumber++);
>> - var submitCell = submitRow.insertCell(0);
>> - var submit = document.createElement('input');
>> -
>> - submit.type = 'submit';
>> - submitCell.colSpan = 2;
>> - submitCell.appendChild(submit);
>> - submitCell.className = 'submit';
>> -
>> - return form;
>> - }
>> -
>> -//last two parameters (selectedMod and savedArgs are only needed for PluginModule
>> - function build_plugin_form_row(row, name, label_name, requiredOrSpecial, value, description, paramDef, selectedMod, savedArgs) {
>> -
>> - var label = row.insertCell(0);
>> - var field = row.insertCell(1);
>> - row.className = 'form-group';
>> - row.id = 'param_' + name;
>> -
>> - label.innerHTML = label_name;
>> - label.className = 'col-sm-3';
>> - field.className = 'col-sm-9';
>> - switch (requiredOrSpecial) {
>> - case (true):  // required flag
>> - label.style.fontWeight = 'bold';
>> - break;
>> - case ('extra') :
>> - label.style.fontStyle = 'italic';
>> - }
>> -
>> - var input, icon;
>> - if (paramDef && paramDef.options) {
>> - input = document.createElement('select');
>> - input.name = 'params[' + name + ']';
>> - input.className = 'form-control';
>> - for (var o = 0; o < paramDef.options.length; o++) {
>> - var opt = document.createElement('option');
>> - opt.value = paramDef.options[o].value;
>> - var opt_text = document.createTextNode(paramDef.options[o].text);
>> - opt.appendChild(opt_text);
>> - //either not PluginModule or user has not changed module selection, so use saved value
>> - if (typeof selectedMod == 'undefined') {
>> - if (value && opt.value == value) {
>> - opt.selected = true;
>> - }
>> - } else {
>> - //user changed module selection in PluginModule
>> - if (selectedMod == opt.value) {
>> - opt.selected = true;
>> - } else if (savedArgs.module == opt.value) {
>> - //use later to display saved module parameter value
>> - var savedtext = opt.innerHTML;
>> - opt.style.fontWeight = 'bold';
>> - opt.innerHTML = opt.innerHTML + '  -- ' + tr('saved value');
>> - }
>> - }
>> - input.appendChild(opt);
>> - }
>> - } else {
>> - input = document.createElement('input');
>> - input.className = 'form-control';
>> - input.type = 'text';
>> - input.name = 'params[' + name + ']';
>> - if (value) {
>> - input.value = value.replace(/\\"/g, '"'); // unescape quotes
>> - }
>> - }
>> -
>> - field.appendChild(input);
>> - if (paramDef && paramDef.type == 'image') {
>> - icon = document.createElement('img');
>> - icon.src = 'img/icons/image.png';
>> - input.id = paramDef.area ? paramDef.area : 'fgal_picker';
>> - icon.onclick = function () {
>> - openFgalsWindowArea(paramDef.area ? paramDef.area : 'fgal_picker');
>> - };
>> - field.appendChild(icon);
>> - } else if (paramDef && paramDef.type == 'fileId') {
>> - var help = document.createElement('span');
>> - input.id = paramDef.area ? paramDef.area : 'fgal_picker';
>> - help.onclick = function () {
>> - openFgalsWindowArea(paramDef.area ? paramDef.area : 'fgal_picker');
>> - };
>> - help.innerHTML = " <a href='#'>" + tr('Pick a file.') + "</a>";
>> - field.appendChild(help);
>> - } else if (paramDef && paramDef.type == 'kaltura') {
>> - input.id = paramDef.area;
>> - var img = $("<img />")
>> - .attr("src", paramDef.icon)
>> - .addClass("icon")
>> - .css("cursor", "pointer")
>> - .attr("title", tr("Upload or record media"))
>> - ;
>> - $(field).append(
>> - $('<a/>')
>> - .attr('href', $.service('kaltura', 'upload'))
>> - .append(img)
>> - .click(function () {
>> - $(this).serviceDialog({
>> - title: tr("Upload or record media"),
>> - width: 710,
>> - height: 450,
>> - hideButtons: true,
>> - success: function (data) {
>> - if (data.entries) {
>> - input.value = data.entries[0];
>> - }
>> - }
>> - });
>> - return false;
>> - })
>> - );
>> - }
>> -
>> - if (description) {
>> - var desc = document.createElement('div');
>> - desc.style.fontSize = 'x-small';
>> - desc.innerHTML = description;
>> - field.appendChild(desc);
>> - }
>> - if (paramDef && paramDef.accepted) {
>> - $(field).append(
>> - $("<div>")
>> - .css("fontSize", "x-small")
>> - .html("<strong>" + tr("Accepted:") + "</strong><br>" + paramDef.accepted)[0]
>> - );
>> - }
>> - //in PluginModule, show saved nodule parameter value if user has changed selection
>> - //since the form changes to match the newly selected module, it's useful to show the
>> - //saved module parameter so the user can go back to it
>> - if (typeof savedtext != 'undefined') {
>> - var saved = document.createElement('div');
>> - saved.style.fontSize = 'x-small';
>> - saved.style.fontStyle = 'italic';
>> - saved.style.fontWeight = 'bold';
>> - saved.innerHTML = tr('Saved value:') + ' ' + savedtext;
>> - field.appendChild(saved);
>> - }
>> -
>> - if (paramDef && paramDef.filter) {
>> - if (paramDef.filter == "pagename") {
>> - $(input).tiki("autocomplete", "pagename");
>> - } else if (paramDef.filter == "groupname") {
>> - $(input).tiki("autocomplete", "groupname", {multiple: true, multipleSeparator: "|"});
>> - } else if (paramDef.filter == "username") {
>> - $(input).tiki("autocomplete", "username", {multiple: true, multipleSeparator: "|"});
>> - } else if (paramDef.filter == "date") {
>> - $(input).tiki("datepicker");
>> - }
>> - }
>> -
>> - }
>> -
>> - function openFgalsWindowArea(area) {
>> - openFgalsWindow('tiki-list_file_gallery.php?filegals_manager=' + area + '&galleryId=' + jqueryTiki.home_file_gallery, true); // reload
>> - }
>> -
>> })(jQuery);
>>
>> Copied: trunk/templates/plugin/edit.tpl (from rev 61597, trunk/templates/plugin/list.tpl)
>> ===================================================================
>> --- trunk/templates/plugin/edit.tpl                        (rev 0)
>> +++ trunk/templates/plugin/edit.tpl 2017-03-13 14:58:28 UTC (rev 61664)
>> @@ -0,0 +1,116 @@
>> +{extends 'layout_view.tpl'}
>> +
>> +{block name="title"}
>> + <h3>{$title}</h3>
>> +{/block}
>> +
>> +{block name="content"}
>> + {function plugin_edit_row}{* needs to be in the same block it seems? *}
>> + {if $param.area}{$inputId=$param.area|escape}{else}{$inputId="param_{$name|escape}_input"}{/if}
>> + <div  class="col-sm-3">
>> + <label for="{$inputId}">{$param.name|escape}</label>
>> + {if not empty($param.type)}
>> + {$onclick = "openFgalsWindow('{$prefs.home_file_gallery|sefurl:'file gallery':true}filegals_manager={$param.area|escape}&id=1', true);return false;"}
>> + {if $param.type eq 'image'}
>> + <br>{icon name='image' title='{tr}Select image{/tr}' onclick=$onclick class='btn btn-xs btn-default'}
>> + {elseif $param.type eq 'fileId'}
>> + <br>{icon name='file' title='{tr}Pick a file{/tr}' onclick=$onclick class='btn btn-xs btn-default'}
>> + {elseif $param.type eq 'kaltura'}
>> + {jq}
>> +$("#picker_{{$name|escape}}").parent().click(function () {
>> + $(this).serviceDialog({
>> + title: tr("Upload or record media"),
>> + width: 710,
>> + height: 450,
>> + hideButtons: true,
>> + success: function (data) {
>> + if (data.entries) {
>> + input.value = data.entries[0];
>> + }
>> + }
>> + });
>> + return false;
>> +});
>> + {/jq}
>> + <br>{icon name='video' title='{tr}Upload or record media{/tr}' href={service controller='kaltura' action='upload'} id='picker_'|cat:$name|escape class='btn btn-xs btn-default'}
>> + {/if}
>> + {/if}
>> + </div>
>> + <div class="col-sm-9">
>> + {if (not empty($param.parent.name))}
>> + {$groupClass = " group-`$param.parent.name`"}
>> + {else}
>> + {$groupClass = ''}
>> + {/if}
>> + {if empty($param.options)}
>> + <input value="{if isset($pluginArgs[$name])}{$pluginArgs[$name]}{/if}" class="form-control{$groupClass}" id="{$inputId}" type="text" name="params[{$name|escape}]">
>> + {if not empty($param.filter)}
>> + {if $param.filter eq "pagename"}
>> + {jq}$({{$inputId}}).tiki("autocomplete", "pagename");{/jq}
>> + {elseif $param.filter eq "groupname"}
>> + {jq}$({{$inputId}}).tiki("autocomplete", "groupname", {multiple: true, multipleSeparator: "|"});{/jq}
>> + {elseif $param.filter eq "username"}
>> + {jq}$({{$inputId}}).tiki("autocomplete", "username", {multiple: true, multipleSeparator: "|"});{/jq}
>> + {elseif $param.filter eq "date"}
>> + {jq}$({{$inputId}}).tiki("datepicker");{/jq}
>> + {/if}
>> + {/if}
>> +
>> + {else}
>> + <select class="form-control{$groupClass}" type="text" name="params[{$name|escape}]" id="{$inputId}">
>> + {foreach $param.options as $option}
>> + <option value="{$option.value|escape}" {if isset($pluginArgs[$name]) and $pluginArgs[$name] eq $option.value} selected="selected"{/if}>
>> + {$option.text|escape}
>> + </option>
>> + {/foreach}
>> + </select>
>> + {/if}
>> + <div class="description">{$param.description}</div>
>> + </div>
>> + {/function}
>> + <div class="form-horizontal" id="plugin_params">
>> + <form action="{service controller='plugin' action='edit'}" method="post">
>> + {foreach $info.params as $name => $param}
>> + <div class="form-group{if $param.advanced} advanced{/if}" id="param_{$name|escape}">
>> + {plugin_edit_row param=$param name=$name info=$info pluginArgs=$pluginArgs}
>> + </div>
>> + {/foreach}
>> + {if not empty($info.advancedParams)}
>> + {button _text='Advanced' _onclick="$('.form-group.advanced.default').toggle('fast'); return false;" _class='btn btn-xs margin-bottom-md'}
>> + {foreach $info.advancedParams as $name => $param}
>> + <div class="form-group advanced default" style="display: none;">
>> + {plugin_edit_row param=$param name=$name info=$info pluginArgs=$pluginArgs}
>> + </div>
>> + {/foreach}
>> + {/if}
>> +
>> + <div class="form-group"{if empty($info.body)} style="display:none"{/if}>
>> + <label for="content" class="col-sm-3">{tr}Body{/tr}</label>
>> + <div class="col-sm-9">
>> + <textarea name="content" id="content" class="form-control">{$bodyContent|escape}</textarea>
>> + <div class="description">{$info.body}</div>
>> + </div>
>> + </div>
>> +
>> + <div class="submit">
>> + <input type="hidden" name="page" value="{$pageName}">
>> + <input type="hidden" name="type" value="{$type}">
>> + <input type="hidden" name="index" value="{$index}">
>> + <input type="hidden" name="args" value="{$pluginArgsJSON}">
>> + <input type="submit" class="btn btn-primary" value="{tr}Save{/tr}">
>> + </div>
>> +
>> + {if $type eq 'module'}
>> + {jq}$("#param_module_input").change(function () {
>> + var selectMod = $(this).val();
>> + $.closeModal();
>> + $(document).one("hidden.bs.modal", function () {
>> + popupPluginForm("{{$area_id}}","{{$type}}", {{$index}}, "{{$pageName}}", {{$pluginArgsJSON}}, "{{$bodyContent}}", "{{$edit_icon}}", selectMod);
>> + });
>> + });{/jq}
>> + {/if}
>> +
>> + </form>
>> + </div>
>> +{/block}
>> +
>>
>> Modified: trunk/tiki-wikiplugin_edit.php
>> ===================================================================
>> --- trunk/tiki-wikiplugin_edit.php 2017-03-13 12:09:36 UTC (rev 61663)
>> +++ trunk/tiki-wikiplugin_edit.php 2017-03-13 14:58:28 UTC (rev 61664)
>> @@ -10,62 +10,9 @@
>>
>> require 'tiki-setup.php';
>>
>> -if ( ! isset( $_POST['page'], $_POST['content'], $_POST['index'], $_POST['type'], $_SERVER['HTTP_REFERER'] ) )
>> - die( 'Missing parameters' );
>> +trigger_error(tr('Note, deprecated file tiki-wikiplugin_edit.php, code moved to service plugin->replace'));
>>
>> -$page = $_POST['page'];
>> +TikiLib::lib('service')->render('plugin', 'replace', $jitPost);
>>
>> -$plugin = strtolower(basename($_POST['type']));
>> -$type = TikiLib::strtoupper($plugin);
>> -
>> -if (empty($parserlib)) {
>> - $parserlib = TikiLib::lib('parser');
>> -}
>> -
>> -if ( ! $meta = $parserlib->plugin_info($plugin) )
>> - exit;
>> -
>> -if ( ! isset( $_POST['message'] ) )
>> - $_POST['message'] = (isset($meta['name']) ? tra($meta['name']) : $plugin) . ' ' . tra('Plugin modified by editor.');
>> -
>> -$info = $tikilib->get_page_info($page);
>> -$tikilib->get_perm_object($page, 'wiki page', $info, true);
>> -if ($tiki_p_edit != 'y') {
>> - header("Location: {$_SERVER['HTTP_REFERER']}");
>> - exit;
>> -}
>> -$content = $_POST['content'];
>> -$current = $info['data'];
>> -
>> -$matches = WikiParser_PluginMatcher::match($current);
>> -$count = 0;
>> -foreach ( $matches as $match ) {
>> - if ( $match->getName() !== $plugin ) {
>> - continue;
>> - }
>> -
>> - ++$count;
>> -
>> - if ( $_POST['index'] == $count ) {
>> - //by using content of "~same~", it will not replace the body that is there
>> - $content = ($content == "~same~" ? $match->getBody() : $content);
>> - $params = $match->getArguments();
>> -
>> - // If parameters are provided, rebuild the parameter line
>> - if ( isset( $_POST['params'] ) && is_array($_POST['params']) ) {
>> - // $values was relaxed to accept any argument rather than those defined up front
>> - // in the plugin's parameter list. This facilitates the use of modules as plugins.
>> - $params = $_POST['params'];
>> - }
>> -
>> - $match->replaceWithPlugin($plugin, $params, $content);
>> -
>> - $parsed = $matches->getText();
>> -
>> - $tikilib->update_page($page, $parsed, $_POST['message'], $user, $tikilib->get_ip_address());
>> - break;
>> - }
>> -}
>> -
>> header("Location: {$_SERVER['HTTP_REFERER']}");
>> exit;
>>
>> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
>>
>>
>> ------------------------------------------------------------------------------
>> Check out the vibrant tech community on one of the world's most
>> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
>> _______________________________________________
>> Tikiwiki-cvs mailing list
>> [hidden email]
>> https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
>>
>
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> TikiWiki-devel mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
TikiWiki-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]

gezzzan
wow, great step forward, thanks jonny!

agree with lindon, can it be wider? I think there is a class for that (modal-lg)

having it wider would also be great to split the modal horizontally into two panes, left with the parameters and right with a preview where you have a refresh button and the output is rendered on click so you can see the effects of your parameter settings right away without needing to save

would be nice to have vertical scrolling for the parameter pane in case there are lots of parameters

thanks again!
cheers,
gezza


From: lindon <[hidden email]>
To: Tiki developers <[hidden email]>
Sent: Tuesday, March 14, 2017 4:50 AM
Subject: Re: [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]

Impressive work Jonny - many thanks for this great leap forward!

Taking a quick look I was wondering if it were possible for the popups to be any wider. If not, we’ll need to cut down on the help text in some places, which is probably a good idea anyway :) Also miss the scrollbar a little (but not much!). All in all, seems to be working very well and it’s may be just a matter of getting used to the things I mentioned rather than changing anything.

Thanks again - well done.
Regards,
lindon


> On Mar 13, 2017, at 11:11 AM, Jonny Bradley <[hidden email]> wrote:
>
> Hi all
>
> This is a quite big change for Tiki 17, and really quite overdue and needed for the list plugin GUI, which i'm hoping now to add before we branch (for which thank you Marc!)
>
> Plugin edit forms are now created sever-side so we can use a template (templates/plugin/edit.tpl) to build the form and all the goodness of a php service lib/core/Services/Edit/PluginController.php for processing it. Rather than re-creating the ancient custom js validation i've used the jquery validator (if the feature is enabled) which i think works better and will be more useful in the future.
>
> In the future we should be able to extend this method for editing plugins to other objects, not just wiki pages.
>
> Anyway, as with many of these big changes there isn't a huge amount to see that's new (yet) and something somewhere is bound to have borken so please do let me know if you find anything related to this that's fallen off!
>
> Thanks,
>
> jonny
>
>
>
>
>> On 13 Mar 2017, at 14:58, [hidden email] wrote:
>>
>> Revision: 61664
>> Author:  jonnybradley
>> Date:    2017-03-13 14:58:28 +0000 (Mon, 13 Mar 2017)
>> Log Message:
>> -----------
>> [MOD] plugins: Move plugin edit form processing to a serverside AJAX service.
>> TODO Switch over remaining usages of tiki-wikiplugin_edit.php to service plugin replace and remove that and tiki*js.php files
>> Probably further tidying up and fixes to do too, please advice of any breakages (thanks marcalporte)
>>
>> Modified Paths:
>> --------------
>>  trunk/lib/core/Services/Edit/PluginController.php
>>  trunk/lib/jquery_tiki/tiki-pluginedit.js
>>  trunk/tiki-wikiplugin_edit.php
>>
>> Added Paths:
>> -----------
>>  trunk/templates/plugin/edit.tpl
>>
>> Modified: trunk/lib/core/Services/Edit/PluginController.php
>> ===================================================================
>> --- trunk/lib/core/Services/Edit/PluginController.php    2017-03-13 12:09:36 UTC (rev 61663)
>> +++ trunk/lib/core/Services/Edit/PluginController.php    2017-03-13 14:58:28 UTC (rev 61664)
>> @@ -17,7 +17,7 @@
>>
>>     function __construct()
>>     {
>> -        $this->parserlib = TikiLib::lib('parser');
>> +        $this->pluginList = [];
>>     }
>>
>>     function setUp()
>> @@ -27,7 +27,12 @@
>>         $this->pluginList = TikiLib::lib('wiki')->list_plugins(true);
>>     }
>>
>> -
>> +    /**
>> +    * List all or some of theplugins for the textarea control panel
>> +    *
>> +    * @param JitFilter $input
>> +    * @return array
>> +    */
>>     function action_list($input)
>>     {
>>         $filter = $input->filter->text();
>> @@ -41,7 +46,7 @@
>>         }
>>         $results = TikiLib::lib('prefs')->getMatchingPreferences($query);
>>
>> -        foreach($results as $result) {
>> +        foreach ($results as $result) {
>>             if (strpos($result, 'wikiplugin_') === 0) {
>>                 $key = strtoupper(substr($result, 11));
>>                 $arr = array_filter($this->pluginList, function ($plugin) use ($key) {
>> @@ -72,6 +77,214 @@
>>         );
>>     }
>>
>> +    /**
>> +    * Display plugin edit form or process saving changes
>> +    *
>> +    * @param JitFilter $input
>> +    * @return array
>> +    * @throws Services_Exception_BadRequest
>> +    * @throws Services_Exception_Denied
>> +    */
>> +    function action_edit($input)
>> +    {
>> +        global $prefs;
>> +
>> +        $parserlib = TikiLib::lib('parser');
>> +
>> +        $area_id = $input->area_id->alnumdash();
>> +        $type = $input->type->word();
>> +        $index = $input->index->int();
>> +        $page = $input->page->pagename();
>> +        $pluginArgs = $input->pluginArgs->array();
>> +        $bodyContent = $input->bodyContent->wikicontent();
>> +        $edit_icon = $input->edit_icon->text();
>> +        $selectedMod = $input->selectedMod->text();
>> +
>> +        $tikilib = TikiLib::lib('tiki');
>> +        $pageInfo = $tikilib->get_page_info($page);
>> +        if (! $pageInfo) {
>> +            // in edit mode
>> +        } else {
>> +            $perms = $tikilib->get_perm_object($page, 'wiki page', $pageInfo, false);
>> +            if ($perms['tiki_p_edit'] !== 'y') {
>> +                throw new Services_Exception_Denied(tr('You do not have permission to edit "%0"', $page));
>> +            }
>> +        }
>> +
>> +
>> +        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
>> +
>> +            $this->action_replace($input);
>> +
>> +            return [
>> +                'redirect' => TikiLib::lib('wiki')->sefurl($page),
>> +            ];
>> +
>> +        } else {        // render the form
>> +
>> +            $info = $parserlib->plugin_info($type);
>> +            $info['advancedParams'] = [];
>> +            $validationRules = [];
>> +
>> +            foreach ($info['params'] as $key => $param) {
>> +                if ($prefs['feature_jquery_validation'] === 'y') {
>> +                    // $("#insertItemForm4").validate({rules: { ins_11: { required: true}, ins_13: { remote: { url: "validate-ajax.php", type: "post", data: { validator: "distinct", parameter: "trackerId=4&fieldId=13&itemId=0", message: "", input: function() { return $("#ins_13").val(); } } } }, ins_18: { required: true, remote: { url: "validate-ajax.php", type: "post", data: { validator: "distinct", parameter: "trackerId=4&fieldId=18&itemId=0", message: "this is not distinct!", input: function() { return $("#ins_18").val(); } } } }}, messages: { ins_11: { required: "This field is required" }, ins_18: { required: "this is not distinct!" }},
>> +                    if ($param['required']) {
>> +                        if (empty($param['parent'])) {
>> +                            $validationRules["params[$key]"] = ['required' => true];
>> +                        } else {
>> +                            $validationRules["params[$key]"] = ['required_in_group' => [
>> +                                1,
>> +                                '.group-' . $param['parent']['name'],
>> +                                'other',
>> +                            ]];
>> +                        }
>> +                    }
>> +                }
>> +                if (! empty($param['advanced']) && ! isset($pluginArgs[$key]) && empty($param['parent'])) {
>> +                    $info['advancedParams'][$key] = $param;
>> +                    unset($info['params'][$key]);
>> +                }
>> +            }
>> +
>> +            if ($validationRules) {
>> +                $rules = json_encode(['rules' => $validationRules]);
>> +                TikiLib::lib('header')->add_jq_onready('$("#plugin_params > form").validate(' . $rules . ');');
>> +            }
>> +
>> +            if ($type === 'module' && isset($pluginArgs['module'])) {
>> +                if ($selectedMod) {
>> +                    $pluginArgs['module'] = $selectedMod;
>> +                }
>> +                $file = 'modules/mod-func-' . $pluginArgs['module'] . '.php';
>> +                if (file_exists($file)) {
>> +                    include_once($file);
>> +                    $info_func = "module_{$pluginArgs['module']}_info";
>> +                    if (function_exists($info_func)) {
>> +                        $moduleInfo = $info_func();
>> +                        if (isset($info['params']['max'])) {
>> +                            $max = $info['params']['max'];
>> +                            unset($info['params']['max']);    // move "max" to last
>> +                        }
>> +                        foreach($moduleInfo['params'] as $key => $value) {
>> +                            $info['params'][$key] = $value;
>> +                        }
>> +                        if (! empty($max)) {
>> +                            $info['params']['max'] = $max;
>> +                        }
>> +                        // replace the module plugin description with the one from the select module
>> +                        $info['params']['module']['description'] = $moduleInfo['description'];
>> +                    }
>> +
>> +                }
>> +            }
>> +
>> +            return [
>> +                // pass back the input parameters
>> +                'area_id' => $area_id,
>> +                'type' => $type,
>> +                'index' => $index,
>> +                'pageName' => $page,
>> +                'pluginArgs' => $pluginArgs,
>> +                'pluginArgsJSON' => json_encode($pluginArgs),
>> +                'bodyContent' => $bodyContent,
>> +                'edit_icon' => $edit_icon,
>> +                'selectedMod' => $selectedMod,
>> +
>> +                'info' => $info,
>> +                'title' => $type,
>> +            ];
>> +        }
>> +    }
>> +
>> +    /**
>> +    * Replace plugin in wiki content
>> +    * Migrated from tiki-wikiplugin_edit.php
>> +    *
>> +    * @param JitFilter $input
>> +    * @return array
>> +    * @throws Services_Exception
>> +    * @throws Services_Exception_BadRequest
>> +    * @throws Services_Exception_Denied
>> +    */
>> +    function action_replace($input)
>> +    {
>> +        global $user;
>> +
>> +        $tikilib = TikiLib::lib('tiki');
>> +        $parserlib = TikiLib::lib('parser');
>> +
>> +        $page = $input->page->pagename();
>> +        $type = $input->type->word();
>> +        $message = $input->message->text();
>> +        $content = $input->content->wikicontent();
>> +        $index = $input->index->int();
>> +        $params = $input->params->array();
>> +
>> +        $referer = $_SERVER['HTTP_REFERER'];
>> +
>> +        if (! $page || ! $type || ! $referer || $_SERVER['REQUEST_METHOD'] !== 'POST') {
>> +            throw new Services_Exception(tr('Missing parameters'));
>> +        }
>> +
>> +        $plugin = strtolower($type);
>> +        $meta = $parserlib->plugin_info($plugin);
>> +
>> +        if (! $page || ! $type || ! $referer) {
>> +            throw new Services_Exception(tr('Plugin "%0" not found', $plugin));
>> +        }
>> +
>> +        if (! $message) {
>> +            $message = tr('%0 Plugin modified by editor.', $plugin);
>> +        }
>> +
>> +        $info = $tikilib->get_page_info($page);
>> +        if (! $info) {
>> +            throw new Services_Exception_BadRequest(tr('Page "%0" not found', $page));
>> +        }
>> +
>> +        $perms = $tikilib->get_perm_object($page, 'wiki page', $info, false);
>> +        if ($perms['tiki_p_edit'] !== 'y') {
>> +            throw new Services_Exception_Denied(tr('You do not have permission to edit "%0"', $page));
>> +        }
>> +
>> +        $current = $info['data'];
>> +
>> +        $matches = WikiParser_PluginMatcher::match($current);
>> +        $count = 0;
>> +        foreach ($matches as $match) {
>> +            if ($match->getName() !== $plugin) {
>> +                continue;
>> +            }
>> +
>> +            ++$count;
>> +
>> +            if ($index === $count) {
>> +                // by using content of "~same~", it will not replace the body that is there
>> +                $content = ($content == "~same~" ? $match->getBody() : $content);
>> +
>> +                if (! $params) {
>> +                    $params = $match->getArguments();
>> +                }
>> +
>> +                $match->replaceWithPlugin($plugin, $params, $content);
>> +
>> +                $tikilib->update_page(
>> +                    $page,
>> +                    $matches->getText(),
>> +                    $message,
>> +                    $user,
>> +                    $tikilib->get_ip_address()
>> +                );
>> +
>> +                break;
>> +            }
>> +        }
>> +
>> +        return [];
>> +
>> +    }
>> +
>> }
>>
>>
>>
>> Modified: trunk/lib/jquery_tiki/tiki-pluginedit.js
>> ===================================================================
>> --- trunk/lib/jquery_tiki/tiki-pluginedit.js    2017-03-13 12:09:36 UTC (rev 61663)
>> +++ trunk/lib/jquery_tiki/tiki-pluginedit.js    2017-03-13 14:58:28 UTC (rev 61664)
>> @@ -82,137 +82,30 @@
>>                 replaceText = false;
>>             }
>>         }
>> -        var form = build_plugin_form(type, index, pageName, pluginArgs, bodyContent, selectedMod);
>>
>> -        //with PluginModule, if the user selects another module while the edit form is open
>> -        //replace the form with a new one with fields to match the parameters for the module selected
>> -        $(form).find('tr select[name="params[module]"]').change(function () {
>> -            var npluginArgs = $.parseJSON($(form).find('input[name="args"][type="hidden"]').val());
>> -            //this is the newly selected module
>> -            var selectedMod = $(form).find('tr select[name="params[module]"]').val();
>> -            $('div.plugin input[name="type"][value="' + type + '"]').parent().parent().remove();
>> -            popupPluginForm(area_id, type, index, pageName, npluginArgs, bodyContent, edit_icon, selectedMod);
>> -        });
>> -        var $form = $(form).find('tr input[type=submit]').remove();
>> -
>> -        container.append(form);
>> -
>> -
>> -        var pfc = container.find('table tr').length;    // number of rows (plugin form contents)
>> -        var t = container.find('textarea:visible').length;
>> -        if (t) {
>> -            pfc += t * 3;
>> -        }
>> -        if (pfc > 9) {
>> -            pfc = 9;
>> -        }
>> -        if (pfc < 2) {
>> -            pfc = 2;
>> -        }
>> -        pfc = pfc / 10;            // factor to scale dialog height
>> -
>> -        var $closeBtn = $('<button>')
>> -            .text(tr("Close"))
>> -            .addClass('btn btn-default')
>> -            .click(function () {
>> -                $(this).parents(".modal").modal("hide");
>> -            });
>> -
>> -        var $submitBtn = $('<button>')
>> -            .text(replaceText ? tr("Replace") : edit_icon ? tr("Submit") : tr("Insert"))
>> -            .addClass('btn btn-primary')
>> -            .click(function () {
>> -
>> -                $(this).off("click").css("opacity", 0.3);
>> -
>> -                var meta = tiki_plugins[type];
>> -                var params = [];
>> -                var edit = edit_icon;
>> -                // whether empty required params exist or not
>> -                var emptyRequiredParam = false;
>> -
>> -                for (var i = 0; i < form.elements.length; i++) {
>> -                    var element = form.elements[i].name;
>> -
>> -                    var matches = element.match(/params\[(.*)\]/);
>> -
>> -                    if (matches === null) {
>> -                        // it's not a parameter, skip
>> -                        continue;
>> -                    }
>> -                    var param = matches[1];
>> -
>> -                    var val = form.elements[i].value;
>> -
>> -                    // check if fields that are required and visible are not empty
>> -                    if (meta.params[param]) {
>> -                        if (meta.params[param].required) {
>> -                            if (val === '' && $(form.elements[i]).is(':visible')) {
>> -                                $(form.elements[i]).css('border-color', 'red');
>> -                                if ($(form.elements[i]).next('.required_param').length === 0) {
>> -                                    $(form.elements[i]).after('<div class="required_param" style="font-size: x-small; color: red;">(required)</div>');
>> -                                }
>> -                                emptyRequiredParam = true;
>> -                            }
>> -                            else {
>> -                                // remove required feedback if present
>> -                                $(form.elements[i]).css('border-color', '');
>> -                                $(form.elements[i]).next('.required_param').remove();
>> -                            }
>> -                        }
>> -                    }
>> -
>> -                    if (val !== '') {
>> -                        if (!edit) {
>> -                            val = val.replace(/"/g, '\\"');    // escape double quotes
>> -                        }
>> -                        params.push(param + '="' + val + '"');
>> -                    }
>> -                }
>> -
>> -                if (emptyRequiredParam) {
>> -                    return false;
>> -                }
>> -
>> -                var blob, pluginContentTextarea = $("[name=content]", form),
>> -                    pluginContentTextareaEditor = syntaxHighlighter.get(pluginContentTextarea);
>> -                var cont = (pluginContentTextareaEditor ? pluginContentTextareaEditor.getValue() : pluginContentTextarea.val());
>> -
>> -                if (meta.body) {
>> -                    blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' + cont + '{' + type.toUpperCase() + '}';
>> -                } else {
>> -                    blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}';
>> -                }
>> -
>> -                if (edit) {
>> -                    container.children('form').submit();
>> -                    // quick and dirty reload
>> -                    window.location = window.location.href;
>> -                } else {
>> -                    insertAt(area_id, blob, false, false, replaceText);
>> -                }
>> -                $modal.modal("hide");
>> -
>> -                return false;
>> -            });
>> -
>> -        var heading = container.find('h3').hide();
>> -
>>         var $modal = $('.modal.fade:not(.in)').first();
>>
>> -        $modal.find(".modal-dialog").empty()
>> -            .append($("<div>").addClass("modal-content")
>> -                .append($("<div>").addClass("modal-header").append($("<h4>").addClass("modal-title").text(heading.text())))
>> -                .append($("<div>").addClass("modal-body").append(container))
>> -                .append($("<div>").addClass("modal-footer").append($closeBtn, $submitBtn))
>> -            );
>> +        var url = $.service("plugin", "edit", {
>> +            area_id: area_id,
>> +            type: type,
>> +            index: index,
>> +            page: pageName,
>> +            pluginArgs: pluginArgs,
>> +            bodyContent: bodyContent,
>> +            edit_icon: edit_icon,
>> +            selectedMod: selectedMod ? selectedMod : "",
>> +            modal: 1
>> +        });
>>
>>         // Make the form appear
>> -        $modal.modal({
>> -            show: false            // if it;'s the first time the show.bs.modal doesn't trigger sometimes
>> -        })
>> -            .one('show.bs.modal', function () {            // Bind open event
>> +        $modal
>> +            .modal({
>> +                remote: url,
>> +                show: false            // if it's the first time the show.bs.modal doesn't trigger sometimes
>> +            })
>> +            .one('loaded.bs.modal', function () {            // Bind remote loaded event
>>                 handlePluginFieldsHierarchy(type);
>> +                handleFormSubmit(this, type, edit_icon, area_id, replaceText);
>>             })
>>             .modal("show");
>>
>> @@ -231,7 +124,7 @@
>>                 arguments: arguments,
>>                 modal: $modal
>>             });
>> -    }
>> +    };
>>
>>     /*
>>     * Hides all children fields in a wiki-plugin form and
>> @@ -240,14 +133,15 @@
>>     */
>>     function handlePluginFieldsHierarchy(type) {
>>         var pluginParams = tiki_plugins[type]['params'];
>> +        var $container = $('#plugin_params');
>>
>>         var parents = {};
>>
>>         $.each(pluginParams, function (paramName, paramValues) {
>>             if (paramValues.parent) {
>> -                var $parent = $('[name$="params[' + paramValues.parent.name + ']"]', '.wikiplugin_edit');
>> +                var $parent = $('[name$="params[' + paramValues.parent.name + ']"]', $container);
>>
>> -                var $row = $('.wikiplugin_edit').find('#param_' + paramName);
>> +                var $row = $container.find('#param_' + paramName);
>>                 $row.addClass('parent_' + paramValues.parent.name + '_' + paramValues.parent.value);
>>
>>                 if ($parent.val() !== paramValues.parent.value) {
>> @@ -271,14 +165,69 @@
>>         $.each(parents, function (parentName, parent) {
>>             parent.parentElement.change(function () {
>>                 $.each(parent.children, function () {
>> -                    $('.wikiplugin_edit #param_' + this).hide();
>> +                    $container.find('#param_' + this).hide();
>>                 });
>> -                $('.wikiplugin_edit .parent_' + parentName + '_' + this.value).show();
>> +                $container.find('.parent_' + parentName + '_' + this.value).show();
>>             })
>>                 .change().trigger("chosen:updated");
>>         });
>>     }
>>
>> +    /**
>> +    * set up insert/replace button and submit handler in "textarea" edit mode
>> +    *
>> +    * @param container
>> +    * @param type
>> +    * @param edit_icon
>> +    * @param area_id
>> +    */
>> +    function handleFormSubmit(container, type, edit_icon, area_id, replaceText) {
>> +
>> +        var meta = tiki_plugins[type], params = [], edit = !!edit_icon, emptyRequiredParam = false;
>> +
>> +        var $form = $("form", container);
>> +
>> +        $form.submit(function () {
>> +
>> +            if (!process_submit(this)) {
>> +                return false;
>> +            }
>> +
>> +            $(".form-control", $form).each(function () {
>> +
>> +                var matches = $(this).attr("name").match(/params\[(.*)\]/),
>> +                    val = $(this).val();
>> +
>> +                if (!matches) {
>> +                    // it's not a parameter, skip
>> +                    return;
>> +                }
>> +
>> +                if (val&& !edit) {
>> +                    val = val.replace(/"/g, '\\"');    // escape double quotes
>> +                    params.push(matches[1] + '="' + val + '"');
>> +                }
>> +            });
>> +
>> +            var blob, pluginContentTextarea = $("[name=content]", $form),
>> +                pluginContentTextareaEditor = syntaxHighlighter.get(pluginContentTextarea),
>> +                cont = (pluginContentTextareaEditor ? pluginContentTextareaEditor.getValue() : pluginContentTextarea.val());
>> +
>> +            if (!edit) {
>> +                if (meta.body) {
>> +                    blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' + cont + '{' + type.toUpperCase() + '}';
>> +                } else {
>> +                    blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}';
>> +                }
>> +
>> +                insertAt(area_id, blob, false, false, replaceText);
>> +                $(container).modal("hide");
>> +
>> +                return false;
>> +            }
>> +        });
>> +    }
>> +
>>     function dialogSelectElement(area_id, elementStart, elementEnd) {
>>         if (typeof CKEDITOR !== 'undefined' && typeof CKEDITOR.instances[area_id] !== 'undefined') {
>>             return;
>> @@ -317,325 +266,4 @@
>>
>>     }
>>
>> -
>> -    function build_plugin_form(type, index, pageName, pluginArgs, bodyContent, selectedMod) {
>> -        var form = document.createElement('form');
>> -        form.method = 'post';
>> -        form.action = 'tiki-wikiplugin_edit.php';
>> -        form.className = 'wikiplugin_edit';
>> -
>> -        var hiddenPage = document.createElement('input');
>> -        hiddenPage.type = 'hidden';
>> -        hiddenPage.name = 'page';
>> -        hiddenPage.value = pageName;
>> -        form.appendChild(hiddenPage);
>> -
>> -        var hiddenType = document.createElement('input');
>> -        hiddenType.type = 'hidden';
>> -        hiddenType.name = 'type';
>> -        hiddenType.value = type;
>> -        form.appendChild(hiddenType);
>> -
>> -        var hiddenIndex = document.createElement('input');
>> -        hiddenIndex.type = 'hidden';
>> -        hiddenIndex.name = 'index';
>> -        hiddenIndex.value = index;
>> -        form.appendChild(hiddenIndex);
>> -
>> -        //
>> -        var savedArgs = document.createElement('input');
>> -        savedArgs.type = 'hidden';
>> -        savedArgs.name = 'args';
>> -        savedArgs.value = $.toJSON(pluginArgs);
>> -        form.appendChild(savedArgs);
>> -
>> -        //Convert to JSON and then back to an object to break
>> -        //link between meta local variable and tiki_plugins[type] global variable.
>> -        //Otherwise each change to meta.params using the extend below was being appended to the global
>> -        //Probably a much easier way to do this
>> -        var infostring = $.toJSON(tiki_plugins[type]);
>> -        var meta = $.parseJSON(infostring);
>> -
>> -        //For PluginModule, add selected module parameters to the plugin edit form
>> -        if (type == 'module') {
>> -            //isolate the module parameter object so it will be shown first in the form
>> -            var onlymod = {"params": {"module": meta.params.module}};
>> -            //user has not changed the module selection since opening the form
>> -            if (typeof selectedMod == 'undefined') {
>> -                //pick up the parameters of the saved module parameter
>> -                if (typeof pluginArgs.module != 'undefined') {
>> -                    //this orders the module parameter first, module related parameters second, other PluginModule parameters besides module last
>> -                    meta.params = $.extend(onlymod.params, tiki_module_params[pluginArgs.module].params, meta.params);
>> -                    //Use the module description
>> -                    meta.params.module.description = tiki_module_params[pluginArgs.module].description;
>> -                    //otherwise pick up the parameters of the first module option since that will be selected automatically
>> -                } else {
>> -                    meta.params = $.extend(onlymod.params, tiki_module_params[meta.params.module.options[0].value].params, meta.params);
>> -                    meta.params.module.description = tiki_module_params[meta.params.module.options[0].value].description;
>> -                }
>> -                //user has selected another module while the form was open - pick up parameters for the selected module
>> -            } else if (tiki_module_params[selectedMod] != null) {
>> -                meta.params = $.extend(onlymod.params, tiki_module_params[selectedMod].params, meta.params);
>> -                meta.params.module.description = tiki_module_params[selectedMod].description;
>> -            }
>> -        }
>> -
>> -        var header = document.createElement('h3');
>> -        header.innerHTML = meta.name;
>> -        form.appendChild(header);
>> -
>> -        var desc = document.createElement('div');
>> -        desc.innerHTML = meta.description;
>> -        if (meta.documentation && jqueryTiki.helpurl) {
>> -            desc.innerHTML += ' <a href="' + jqueryTiki.helpurl + meta.documentation + '" target="tikihelp" class="tikihelp" tabIndex="-1" title="' + tr('Help') + '">' +
>> -                '<span class="icon icon-help fa fa-question-circle fa-fw"></span>' +
>> -                '</a>';
>> -
>> -        }
>> -        form.appendChild(desc);
>> -
>> -        var table = document.createElement('table'), param;
>> -        table.className = 'table';
>> -        table.id = 'plugin_params';
>> -        form.appendChild(table);
>> -
>> -        for (param in meta.params) {
>> -            if (meta.params[param].advanced) {
>> -                var br = document.createElement('br');
>> -                form.appendChild(br);
>> -
>> -                var span_advanced_button = document.createElement('span');
>> -                span_advanced_button.className = 'button';
>> -                form.appendChild(span_advanced_button);
>> -
>> -                var advanced_button = document.createElement('a');
>> -                advanced_button.innerHTML = tr('Advanced options');
>> -                advanced_button.onclick = function () {
>> -                    flip('plugin_params_advanced');
>> -                };
>> -                span_advanced_button.appendChild(advanced_button);
>> -
>> -                var table_advanced = document.createElement('table');
>> -                table_advanced.className = 'normal';
>> -                table_advanced.style.display = 'none';
>> -                table_advanced.id = 'plugin_params_advanced';
>> -                form.appendChild(table_advanced);
>> -
>> -                break;
>> -            }
>> -        }
>> -
>> -        var potentiallyExtraPluginArgs = pluginArgs, extraArg;
>> -
>> -        var rowNumber = 0;
>> -        var rowNumberAdvanced = 0;
>> -        for (param in meta.params) {
>> -            if (typeof(meta.params[param]) != 'object' || meta.params[param].name == 'array') {
>> -                continue;
>> -            }
>> -
>> -            var row;
>> -            if (meta.params[param].advanced && !meta.params[param].required && typeof pluginArgs[param] === "undefined") {
>> -                row = table_advanced.insertRow(rowNumberAdvanced++);
>> -            } else {
>> -                row = table.insertRow(rowNumber++);
>> -            }
>> -            var value = pluginArgs.length < 1 ? '' : pluginArgs[param];// for param like sort
>> -            //for use with PluginModule to identify saved module parameter value
>> -            var nsavedArgs = $.parseJSON($(form).find('input[name="args"][type="hidden"]').val());
>> -            //last two parameters (selectedMod and savedArgs are only needed for PluginModule
>> -            build_plugin_form_row(row, param, meta.params[param].name, meta.params[param].required, value, meta.params[param].description, meta.params[param], selectedMod, nsavedArgs);
>> -
>> -            delete potentiallyExtraPluginArgs[param];
>> -        }
>> -
>> -        for (extraArg in potentiallyExtraPluginArgs) {
>> -            if (extraArg === '') {
>> -                // TODO HACK: See bug 2499 http://dev.tiki.org/tiki-view_tracker_item.php?itemId=2499
>> -                continue;
>> -            }
>> -
>> -            row = table.insertRow(rowNumber++);
>> -            build_plugin_form_row(row, extraArg, extraArg, 'extra', pluginArgs[extraArg], extraArg);
>> -        }
>> -
>> -        var bodyRow = table.insertRow(rowNumber++);
>> -        var bodyCell = bodyRow.insertCell(0);
>> -        var bodyField = document.createElement('textarea');
>> -        bodyField.rows = '12';
>> -        bodyField.className = 'form-control';
>> -        var bodyDesc = document.createElement('div');
>> -
>> -        if (meta.body) {
>> -            bodyDesc.innerHTML = meta.body;
>> -        } else {
>> -            bodyRow.style.display = 'none';
>> -        }
>> -        bodyField.name = 'content';
>> -        bodyField.value = bodyContent;
>> -
>> -        bodyRow.className = 'formcolor';
>> -
>> -        bodyCell.appendChild(bodyDesc);
>> -        bodyCell.appendChild(bodyField);
>> -        bodyCell.colSpan = '2';
>> -
>> -        var submitRow = table.insertRow(rowNumber++);
>> -        var submitCell = submitRow.insertCell(0);
>> -        var submit = document.createElement('input');
>> -
>> -        submit.type = 'submit';
>> -        submitCell.colSpan = 2;
>> -        submitCell.appendChild(submit);
>> -        submitCell.className = 'submit';
>> -
>> -        return form;
>> -    }
>> -
>> -//last two parameters (selectedMod and savedArgs are only needed for PluginModule
>> -    function build_plugin_form_row(row, name, label_name, requiredOrSpecial, value, description, paramDef, selectedMod, savedArgs) {
>> -
>> -        var label = row.insertCell(0);
>> -        var field = row.insertCell(1);
>> -        row.className = 'form-group';
>> -        row.id = 'param_' + name;
>> -
>> -        label.innerHTML = label_name;
>> -        label.className = 'col-sm-3';
>> -        field.className = 'col-sm-9';
>> -        switch (requiredOrSpecial) {
>> -            case (true):  // required flag
>> -                label.style.fontWeight = 'bold';
>> -                break;
>> -            case ('extra') :
>> -                label.style.fontStyle = 'italic';
>> -        }
>> -
>> -        var input, icon;
>> -        if (paramDef && paramDef.options) {
>> -            input = document.createElement('select');
>> -            input.name = 'params[' + name + ']';
>> -            input.className = 'form-control';
>> -            for (var o = 0; o < paramDef.options.length; o++) {
>> -                var opt = document.createElement('option');
>> -                opt.value = paramDef.options[o].value;
>> -                var opt_text = document.createTextNode(paramDef.options[o].text);
>> -                opt.appendChild(opt_text);
>> -                //either not PluginModule or user has not changed module selection, so use saved value
>> -                if (typeof selectedMod == 'undefined') {
>> -                    if (value && opt.value == value) {
>> -                        opt.selected = true;
>> -                    }
>> -                } else {
>> -                    //user changed module selection in PluginModule
>> -                    if (selectedMod == opt.value) {
>> -                        opt.selected = true;
>> -                    } else if (savedArgs.module == opt.value) {
>> -                        //use later to display saved module parameter value
>> -                        var savedtext = opt.innerHTML;
>> -                        opt.style.fontWeight = 'bold';
>> -                        opt.innerHTML = opt.innerHTML + '  -- ' + tr('saved value');
>> -                    }
>> -                }
>> -                input.appendChild(opt);
>> -            }
>> -        } else {
>> -            input = document.createElement('input');
>> -            input.className = 'form-control';
>> -            input.type = 'text';
>> -            input.name = 'params[' + name + ']';
>> -            if (value) {
>> -                input.value = value.replace(/\\"/g, '"');    // unescape quotes
>> -            }
>> -        }
>> -
>> -        field.appendChild(input);
>> -        if (paramDef && paramDef.type == 'image') {
>> -            icon = document.createElement('img');
>> -            icon.src = 'img/icons/image.png';
>> -            input.id = paramDef.area ? paramDef.area : 'fgal_picker';
>> -            icon.onclick = function () {
>> -                openFgalsWindowArea(paramDef.area ? paramDef.area : 'fgal_picker');
>> -            };
>> -            field.appendChild(icon);
>> -        } else if (paramDef && paramDef.type == 'fileId') {
>> -            var help = document.createElement('span');
>> -            input.id = paramDef.area ? paramDef.area : 'fgal_picker';
>> -            help.onclick = function () {
>> -                openFgalsWindowArea(paramDef.area ? paramDef.area : 'fgal_picker');
>> -            };
>> -            help.innerHTML = " <a href='#'>" + tr('Pick a file.') + "</a>";
>> -            field.appendChild(help);
>> -        } else if (paramDef && paramDef.type == 'kaltura') {
>> -            input.id = paramDef.area;
>> -            var img = $("<img />")
>> -                .attr("src", paramDef.icon)
>> -                .addClass("icon")
>> -                .css("cursor", "pointer")
>> -                .attr("title", tr("Upload or record media"))
>> -            ;
>> -            $(field).append(
>> -                $('<a/>')
>> -                    .attr('href', $.service('kaltura', 'upload'))
>> -                    .append(img)
>> -                    .click(function () {
>> -                        $(this).serviceDialog({
>> -                            title: tr("Upload or record media"),
>> -                            width: 710,
>> -                            height: 450,
>> -                            hideButtons: true,
>> -                            success: function (data) {
>> -                                if (data.entries) {
>> -                                    input.value = data.entries[0];
>> -                                }
>> -                            }
>> -                        });
>> -                        return false;
>> -                    })
>> -            );
>> -        }
>> -
>> -        if (description) {
>> -            var desc = document.createElement('div');
>> -            desc.style.fontSize = 'x-small';
>> -            desc.innerHTML = description;
>> -            field.appendChild(desc);
>> -        }
>> -        if (paramDef && paramDef.accepted) {
>> -            $(field).append(
>> -                $("<div>")
>> -                    .css("fontSize", "x-small")
>> -                    .html("<strong>" + tr("Accepted:") + "</strong><br>" + paramDef.accepted)[0]
>> -            );
>> -        }
>> -        //in PluginModule, show saved nodule parameter value if user has changed selection
>> -        //since the form changes to match the newly selected module, it's useful to show the
>> -        //saved module parameter so the user can go back to it
>> -        if (typeof savedtext != 'undefined') {
>> -            var saved = document.createElement('div');
>> -            saved.style.fontSize = 'x-small';
>> -            saved.style.fontStyle = 'italic';
>> -            saved.style.fontWeight = 'bold';
>> -            saved.innerHTML = tr('Saved value:') + ' ' + savedtext;
>> -            field.appendChild(saved);
>> -        }
>> -
>> -        if (paramDef && paramDef.filter) {
>> -            if (paramDef.filter == "pagename") {
>> -                $(input).tiki("autocomplete", "pagename");
>> -            } else if (paramDef.filter == "groupname") {
>> -                $(input).tiki("autocomplete", "groupname", {multiple: true, multipleSeparator: "|"});
>> -            } else if (paramDef.filter == "username") {
>> -                $(input).tiki("autocomplete", "username", {multiple: true, multipleSeparator: "|"});
>> -            } else if (paramDef.filter == "date") {
>> -                $(input).tiki("datepicker");
>> -            }
>> -        }
>> -
>> -    }
>> -
>> -    function openFgalsWindowArea(area) {
>> -        openFgalsWindow('tiki-list_file_gallery.php?filegals_manager=' + area + '&galleryId=' + jqueryTiki.home_file_gallery, true);    // reload
>> -    }
>> -
>> })(jQuery);
>>
>> Copied: trunk/templates/plugin/edit.tpl (from rev 61597, trunk/templates/plugin/list.tpl)
>> ===================================================================
>> --- trunk/templates/plugin/edit.tpl                            (rev 0)
>> +++ trunk/templates/plugin/edit.tpl    2017-03-13 14:58:28 UTC (rev 61664)
>> @@ -0,0 +1,116 @@
>> +{extends 'layout_view.tpl'}
>> +
>> +{block name="title"}
>> +    <h3>{$title}</h3>
>> +{/block}
>> +
>> +{block name="content"}
>> +    {function plugin_edit_row}{* needs to be in the same block it seems? *}
>> +        {if $param.area}{$inputId=$param.area|escape}{else}{$inputId="param_{$name|escape}_input"}{/if}
>> +        <div  class="col-sm-3">
>> +            <label for="{$inputId}">{$param.name|escape}</label>
>> +            {if not empty($param.type)}
>> +                {$onclick = "openFgalsWindow('{$prefs.home_file_gallery|sefurl:'file gallery':true}filegals_manager={$param.area|escape}&id=1', true);return false;"}
>> +                {if $param.type eq 'image'}
>> +                    <br>{icon name='image' title='{tr}Select image{/tr}' onclick=$onclick class='btn btn-xs btn-default'}
>> +                {elseif $param.type eq 'fileId'}
>> +                    <br>{icon name='file' title='{tr}Pick a file{/tr}' onclick=$onclick class='btn btn-xs btn-default'}
>> +                {elseif $param.type eq 'kaltura'}
>> +                    {jq}
>> +$("#picker_{{$name|escape}}").parent().click(function () {
>> +    $(this).serviceDialog({
>> +        title: tr("Upload or record media"),
>> +        width: 710,
>> +        height: 450,
>> +        hideButtons: true,
>> +        success: function (data) {
>> +            if (data.entries) {
>> +                input.value = data.entries[0];
>> +            }
>> +        }
>> +    });
>> +    return false;
>> +});
>> +                    {/jq}
>> +                    <br>{icon name='video' title='{tr}Upload or record media{/tr}' href={service controller='kaltura' action='upload'} id='picker_'|cat:$name|escape class='btn btn-xs btn-default'}
>> +                {/if}
>> +            {/if}
>> +        </div>
>> +        <div class="col-sm-9">
>> +            {if (not empty($param.parent.name))}
>> +                {$groupClass = " group-`$param.parent.name`"}
>> +            {else}
>> +                {$groupClass = ''}
>> +            {/if}
>> +            {if empty($param.options)}
>> +                <input value="{if isset($pluginArgs[$name])}{$pluginArgs[$name]}{/if}" class="form-control{$groupClass}" id="{$inputId}" type="text" name="params[{$name|escape}]">
>> +                {if not empty($param.filter)}
>> +                    {if $param.filter eq "pagename"}
>> +                        {jq}$({{$inputId}}).tiki("autocomplete", "pagename");{/jq}
>> +                    {elseif $param.filter eq "groupname"}
>> +                        {jq}$({{$inputId}}).tiki("autocomplete", "groupname", {multiple: true, multipleSeparator: "|"});{/jq}
>> +                    {elseif $param.filter eq "username"}
>> +                        {jq}$({{$inputId}}).tiki("autocomplete", "username", {multiple: true, multipleSeparator: "|"});{/jq}
>> +                    {elseif $param.filter eq "date"}
>> +                        {jq}$({{$inputId}}).tiki("datepicker");{/jq}
>> +                    {/if}
>> +                {/if}
>> +
>> +            {else}
>> +                <select class="form-control{$groupClass}" type="text" name="params[{$name|escape}]" id="{$inputId}">
>> +                    {foreach $param.options as $option}
>> +                        <option value="{$option.value|escape}" {if isset($pluginArgs[$name]) and $pluginArgs[$name] eq $option.value} selected="selected"{/if}>
>> +                            {$option.text|escape}
>> +                        </option>
>> +                    {/foreach}
>> +                </select>
>> +            {/if}
>> +            <div class="description">{$param.description}</div>
>> +        </div>
>> +    {/function}
>> +    <div class="form-horizontal" id="plugin_params">
>> +        <form action="{service controller='plugin' action='edit'}" method="post">
>> +            {foreach $info.params as $name => $param}
>> +                <div class="form-group{if $param.advanced} advanced{/if}" id="param_{$name|escape}">
>> +                    {plugin_edit_row param=$param name=$name info=$info pluginArgs=$pluginArgs}
>> +                </div>
>> +            {/foreach}
>> +            {if not empty($info.advancedParams)}
>> +                {button _text='Advanced' _onclick="$('.form-group.advanced.default').toggle('fast'); return false;" _class='btn btn-xs margin-bottom-md'}
>> +                {foreach $info.advancedParams as $name => $param}
>> +                    <div class="form-group advanced default" style="display: none;">
>> +                        {plugin_edit_row param=$param name=$name info=$info pluginArgs=$pluginArgs}
>> +                    </div>
>> +                {/foreach}
>> +            {/if}
>> +
>> +            <div class="form-group"{if empty($info.body)} style="display:none"{/if}>
>> +                <label for="content" class="col-sm-3">{tr}Body{/tr}</label>
>> +                <div class="col-sm-9">
>> +                    <textarea name="content" id="content" class="form-control">{$bodyContent|escape}</textarea>
>> +                    <div class="description">{$info.body}</div>
>> +                </div>
>> +            </div>
>> +
>> +            <div class="submit">
>> +                <input type="hidden" name="page" value="{$pageName}">
>> +                <input type="hidden" name="type" value="{$type}">
>> +                <input type="hidden" name="index" value="{$index}">
>> +                <input type="hidden" name="args" value="{$pluginArgsJSON}">
>> +                <input type="submit" class="btn btn-primary" value="{tr}Save{/tr}">
>> +            </div>
>> +
>> +            {if $type eq 'module'}
>> +                {jq}$("#param_module_input").change(function () {
>> +                    var selectMod = $(this).val();
>> +                    $.closeModal();
>> +                    $(document).one("hidden.bs.modal", function () {
>> +                        popupPluginForm("{{$area_id}}","{{$type}}", {{$index}}, "{{$pageName}}", {{$pluginArgsJSON}}, "{{$bodyContent}}", "{{$edit_icon}}", selectMod);
>> +                    });
>> +                });{/jq}
>> +            {/if}
>> +
>> +        </form>
>> +    </div>
>> +{/block}
>> +
>>
>> Modified: trunk/tiki-wikiplugin_edit.php
>> ===================================================================
>> --- trunk/tiki-wikiplugin_edit.php    2017-03-13 12:09:36 UTC (rev 61663)
>> +++ trunk/tiki-wikiplugin_edit.php    2017-03-13 14:58:28 UTC (rev 61664)
>> @@ -10,62 +10,9 @@
>>
>> require 'tiki-setup.php';
>>
>> -if ( ! isset( $_POST['page'], $_POST['content'], $_POST['index'], $_POST['type'], $_SERVER['HTTP_REFERER'] ) )
>> -    die( 'Missing parameters' );
>> +trigger_error(tr('Note, deprecated file tiki-wikiplugin_edit.php, code moved to service plugin->replace'));
>>
>> -$page = $_POST['page'];
>> +TikiLib::lib('service')->render('plugin', 'replace', $jitPost);
>>
>> -$plugin = strtolower(basename($_POST['type']));
>> -$type = TikiLib::strtoupper($plugin);
>> -
>> -if (empty($parserlib)) {
>> -    $parserlib = TikiLib::lib('parser');
>> -}
>> -
>> -if ( ! $meta = $parserlib->plugin_info($plugin) )
>> -    exit;
>> -
>> -if ( ! isset( $_POST['message'] ) )
>> -    $_POST['message'] = (isset($meta['name']) ? tra($meta['name']) : $plugin) . ' ' . tra('Plugin modified by editor.');
>> -
>> -$info = $tikilib->get_page_info($page);
>> -$tikilib->get_perm_object($page, 'wiki page', $info, true);
>> -if ($tiki_p_edit != 'y') {
>> -    header("Location: {$_SERVER['HTTP_REFERER']}");
>> -    exit;
>> -}
>> -$content = $_POST['content'];
>> -$current = $info['data'];
>> -
>> -$matches = WikiParser_PluginMatcher::match($current);
>> -$count = 0;
>> -foreach ( $matches as $match ) {
>> -    if ( $match->getName() !== $plugin ) {
>> -        continue;
>> -    }
>> -
>> -    ++$count;
>> -
>> -    if ( $_POST['index'] == $count ) {
>> -        //by using content of "~same~", it will not replace the body that is there
>> -        $content = ($content == "~same~" ? $match->getBody() : $content);
>> -        $params = $match->getArguments();
>> -
>> -        // If parameters are provided, rebuild the parameter line
>> -        if ( isset( $_POST['params'] ) && is_array($_POST['params']) ) {
>> -            // $values was relaxed to accept any argument rather than those defined up front
>> -            // in the plugin's parameter list. This facilitates the use of modules as plugins.
>> -            $params = $_POST['params'];
>> -        }
>> -
>> -        $match->replaceWithPlugin($plugin, $params, $content);
>> -
>> -        $parsed = $matches->getText();
>> -
>> -        $tikilib->update_page($page, $parsed, $_POST['message'], $user, $tikilib->get_ip_address());
>> -        break;
>> -    }
>> -}
>> -
>> header("Location: {$_SERVER['HTTP_REFERER']}");
>> exit;
>>
>> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
>>
>>
>> ------------------------------------------------------------------------------
>> Check out the vibrant tech community on one of the world's most
>> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
>> _______________________________________________
>> Tikiwiki-cvs mailing list
>>
>
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> TikiWiki-devel mailing list


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
TikiWiki-devel mailing list



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
TikiWiki-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]

Jonny Bradley-4

Wider: done :)

Scrolling: works for me by scrolling the window scrollbar, not for you?

jb



> On 14 Mar 2017, at 06:00, gezzzan <[hidden email]> wrote:
>
> wow, great step forward, thanks jonny!
>
> agree with lindon, can it be wider? I think there is a class for that (modal-lg)
>
> having it wider would also be great to split the modal horizontally into two panes, left with the parameters and right with a preview where you have a refresh button and the output is rendered on click so you can see the effects of your parameter settings right away without needing to save
>
> would be nice to have vertical scrolling for the parameter pane in case there are lots of parameters
>
> thanks again!
> cheers,
> gezza
>
>> From: lindon <[hidden email]>
>> To: Tiki developers <[hidden email]>
>> Sent: Tuesday, March 14, 2017 4:50 AM
>> Subject: Re: [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]
>>
>> Impressive work Jonny - many thanks for this great leap forward!
>>
>> Taking a quick look I was wondering if it were possible for the popups to be any wider. If not, we’ll need to cut down on the help text in some places, which is probably a good idea anyway :) Also miss the scrollbar a little (but not much!). All in all, seems to be working very well and it’s may be just a matter of getting used to the things I mentioned rather than changing anything.
>>
>> Thanks again - well done.
>> Regards,
>> lindon
>>
>>
>> > On Mar 13, 2017, at 11:11 AM, Jonny Bradley <[hidden email]> wrote:
>> >
>> > Hi all
>> >
>> > This is a quite big change for Tiki 17, and really quite overdue and needed for the list plugin GUI, which i'm hoping now to add before we branch (for which thank you Marc!)
>> >
>> > Plugin edit forms are now created sever-side so we can use a template (templates/plugin/edit.tpl) to build the form and all the goodness of a php service lib/core/Services/Edit/PluginController.php for processing it. Rather than re-creating the ancient custom js validation i've used the jquery validator (if the feature is enabled) which i think works better and will be more useful in the future.
>> >
>> > In the future we should be able to extend this method for editing plugins to other objects, not just wiki pages.
>> >
>> > Anyway, as with many of these big changes there isn't a huge amount to see that's new (yet) and something somewhere is bound to have borken so please do let me know if you find anything related to this that's fallen off!
>> >
>> > Thanks,
>> >
>> > jonny
>> >
>> >
>> >
>> >
>> >> On 13 Mar 2017, at 14:58, [hidden email] wrote:
>> >>
>> >> Revision: 61664
>> >>        http://sourceforge.net/p/tikiwiki/code/61664
>> >> Author:  jonnybradley
>> >> Date:    2017-03-13 14:58:28 +0000 (Mon, 13 Mar 2017)
>> >> Log Message:
>> >> -----------
>> >> [MOD] plugins: Move plugin edit form processing to a serverside AJAX service.
>> >> TODO Switch over remaining usages of tiki-wikiplugin_edit.php to service plugin replace and remove that and tiki*js.php files
>> >> Probably further tidying up and fixes to do too, please advice of any breakages (thanks marcalporte)
>> >>
>> >> Modified Paths:
>> >> --------------
>> >>  trunk/lib/core/Services/Edit/PluginController.php
>> >>  trunk/lib/jquery_tiki/tiki-pluginedit.js
>> >>  trunk/tiki-wikiplugin_edit.php
>> >>
>> >> Added Paths:
>> >> -----------
>> >>  trunk/templates/plugin/edit.tpl
>> >>
>> >> Modified: trunk/lib/core/Services/Edit/PluginController.php
>> >> ===================================================================
>> >> --- trunk/lib/core/Services/Edit/PluginController.php    2017-03-13 12:09:36 UTC (rev 61663)
>> >> +++ trunk/lib/core/Services/Edit/PluginController.php    2017-03-13 14:58:28 UTC (rev 61664)
>> >> @@ -17,7 +17,7 @@
>> >>
>> >>     function __construct()
>> >>     {
>> >> -        $this->parserlib = TikiLib::lib('parser');
>> >> +        $this->pluginList = [];
>> >>     }
>> >>
>> >>     function setUp()
>> >> @@ -27,7 +27,12 @@
>> >>         $this->pluginList = TikiLib::lib('wiki')->list_plugins(true);
>> >>     }
>> >>
>> >> -
>> >> +    /**
>> >> +    * List all or some of theplugins for the textarea control panel
>> >> +    *
>> >> +    * @param JitFilter $input
>> >> +    * @return array
>> >> +    */
>> >>     function action_list($input)
>> >>     {
>> >>         $filter = $input->filter->text();
[snip]


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
TikiWiki-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]

gezzzan
I meant that the header and the footer of the modal would always be visible and scrolling would apply in the section for the plugin parameters

what do you think, can the preview work?

thanks&cheers,
gezza


From: Jonny Bradley <[hidden email]>
To: gezzzan <[hidden email]>; Tiki developers <[hidden email]>
Sent: Tuesday, March 14, 2017 2:11 PM
Subject: Re: [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]


Wider: done :)

Scrolling: works for me by scrolling the window scrollbar, not for you?

jb



> On 14 Mar 2017, at 06:00, gezzzan <[hidden email]> wrote:
>
> wow, great step forward, thanks jonny!
>
> agree with lindon, can it be wider? I think there is a class for that (modal-lg)
>
> having it wider would also be great to split the modal horizontally into two panes, left with the parameters and right with a preview where you have a refresh button and the output is rendered on click so you can see the effects of your parameter settings right away without needing to save
>
> would be nice to have vertical scrolling for the parameter pane in case there are lots of parameters
>
> thanks again!
> cheers,
> gezza
>
>> From: lindon <[hidden email]>
>> To: Tiki developers <[hidden email]>
>> Sent: Tuesday, March 14, 2017 4:50 AM
>> Subject: Re: [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]
>>
>> Impressive work Jonny - many thanks for this great leap forward!
>>
>> Taking a quick look I was wondering if it were possible for the popups to be any wider. If not, we’ll need to cut down on the help text in some places, which is probably a good idea anyway :) Also miss the scrollbar a little (but not much!). All in all, seems to be working very well and it’s may be just a matter of getting used to the things I mentioned rather than changing anything.
>>
>> Thanks again - well done.
>> Regards,
>> lindon
>>
>>
>> > On Mar 13, 2017, at 11:11 AM, Jonny Bradley <[hidden email]> wrote:
>> >
>> > Hi all
>> >
>> > This is a quite big change for Tiki 17, and really quite overdue and needed for the list plugin GUI, which i'm hoping now to add before we branch (for which thank you Marc!)
>> >
>> > Plugin edit forms are now created sever-side so we can use a template (templates/plugin/edit.tpl) to build the form and all the goodness of a php service lib/core/Services/Edit/PluginController.php for processing it. Rather than re-creating the ancient custom js validation i've used the jquery validator (if the feature is enabled) which i think works better and will be more useful in the future.
>> >
>> > In the future we should be able to extend this method for editing plugins to other objects, not just wiki pages.
>> >
>> > Anyway, as with many of these big changes there isn't a huge amount to see that's new (yet) and something somewhere is bound to have borken so please do let me know if you find anything related to this that's fallen off!
>> >
>> > Thanks,
>> >
>> > jonny
>> >
>> >
>> >
>> >
>> >> On 13 Mar 2017, at 14:58, [hidden email] wrote:
>> >>
>> >> Revision: 61664
>> >> Author:  jonnybradley
>> >> Date:    2017-03-13 14:58:28 +0000 (Mon, 13 Mar 2017)
>> >> Log Message:
>> >> -----------
>> >> [MOD] plugins: Move plugin edit form processing to a serverside AJAX service.
>> >> TODO Switch over remaining usages of tiki-wikiplugin_edit.php to service plugin replace and remove that and tiki*js.php files
>> >> Probably further tidying up and fixes to do too, please advice of any breakages (thanks marcalporte)
>> >>
>> >> Modified Paths:
>> >> --------------
>> >>  trunk/lib/core/Services/Edit/PluginController.php
>> >>  trunk/lib/jquery_tiki/tiki-pluginedit.js
>> >>  trunk/tiki-wikiplugin_edit.php
>> >>
>> >> Added Paths:
>> >> -----------
>> >>  trunk/templates/plugin/edit.tpl
>> >>
>> >> Modified: trunk/lib/core/Services/Edit/PluginController.php
>> >> ===================================================================
>> >> --- trunk/lib/core/Services/Edit/PluginController.php    2017-03-13 12:09:36 UTC (rev 61663)
>> >> +++ trunk/lib/core/Services/Edit/PluginController.php    2017-03-13 14:58:28 UTC (rev 61664)
>> >> @@ -17,7 +17,7 @@
>> >>
>> >>    function __construct()
>> >>    {
>> >> -        $this->parserlib = TikiLib::lib('parser');
>> >> +        $this->pluginList = [];
>> >>    }
>> >>
>> >>    function setUp()
>> >> @@ -27,7 +27,12 @@
>> >>        $this->pluginList = TikiLib::lib('wiki')->list_plugins(true);
>> >>    }
>> >>
>> >> -
>> >> +    /**
>> >> +    * List all or some of theplugins for the textarea control panel
>> >> +    *
>> >> +    * @param JitFilter $input
>> >> +    * @return array
>> >> +    */
>> >>    function action_list($input)
>> >>    {
>> >>        $filter = $input->filter->text();
[snip]



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
TikiWiki-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]

Cloutier, Philippe (RESSOURCE EXTERNE)
In reply to this post by Jonny Bradley-4
Thank you very much Jonny,
I do not understand your edit.tpl comment {* needs to be in the same block it seems? *} (what needs to be in the same block as what?).

I also do not understand why the commit message has [MOD]. Could this disrupt user habits significantly?

> -----Message d'origine-----
> De : Jonny Bradley [mailto:[hidden email]]
> Envoyé : 13 mars 2017 11:12
> À : Tiki developers <[hidden email]>
> Objet : [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]
>
> Hi all
>
> This is a quite big change for Tiki 17, and really quite overdue and needed for the list plugin GUI, which
> i'm hoping now to add before we branch (for which thank you Marc!)
>
> Plugin edit forms are now created sever-side so we can use a template (templates/plugin/edit.tpl) to
> build the form and all the goodness of a php service lib/core/Services/Edit/PluginController.php for
> processing it. Rather than re-creating the ancient custom js validation i've used the jquery validator (if
> the feature is enabled) which i think works better and will be more useful in the future.
>
> In the future we should be able to extend this method for editing plugins to other objects, not just
> wiki pages.
>
> Anyway, as with many of these big changes there isn't a huge amount to see that's new (yet) and
> something somewhere is bound to have borken so please do let me know if you find anything related
> to this that's fallen off!
>
> Thanks,
>
> jonny
>
>
>
>
> > On 13 Mar 2017, at 14:58, [hidden email] wrote:
> >
> > Revision: 61664
> >          http://sourceforge.net/p/tikiwiki/code/61664
> > Author:   jonnybradley
> > Date:     2017-03-13 14:58:28 +0000 (Mon, 13 Mar 2017)
> > Log Message:
> > -----------
> > [MOD] plugins: Move plugin edit form processing to a serverside AJAX service.
> > TODO Switch over remaining usages of tiki-wikiplugin_edit.php to
> > service plugin replace and remove that and tiki*js.php files Probably
> > further tidying up and fixes to do too, please advice of any breakages
> > (thanks marcalporte)
> >
> > Modified Paths:
> > --------------
> >    trunk/lib/core/Services/Edit/PluginController.php
> >    trunk/lib/jquery_tiki/tiki-pluginedit.js
> >    trunk/tiki-wikiplugin_edit.php
> >
> > Added Paths:
> > -----------
> >    trunk/templates/plugin/edit.tpl
> >
> > Modified: trunk/lib/core/Services/Edit/PluginController.php
> > ===================================================================
> > --- trunk/lib/core/Services/Edit/PluginController.php 2017-03-13 12:09:36 UTC (rev 61663)
> > +++ trunk/lib/core/Services/Edit/PluginController.php 2017-03-13 14:58:28 UTC (rev 61664)
> > @@ -17,7 +17,7 @@
> >
> > function __construct()
> > {
> > - $this->parserlib = TikiLib::lib('parser');
> > + $this->pluginList = [];
> > }
> >
> > function setUp()
> > @@ -27,7 +27,12 @@
> > $this->pluginList = TikiLib::lib('wiki')->list_plugins(true);
> > }
> >
> > -
> > + /**
> > + * List all or some of theplugins for the textarea control panel
> > + *
> > + * @param JitFilter $input
> > + * @return array
> > + */
> > function action_list($input)
> > {
> > $filter = $input->filter->text();
> > @@ -41,7 +46,7 @@
> > }
> > $results = TikiLib::lib('prefs')->getMatchingPreferences($query);
> >
> > - foreach($results as $result) {
> > + foreach ($results as $result) {
> > if (strpos($result, 'wikiplugin_') === 0) {
> > $key = strtoupper(substr($result, 11));
> > $arr = array_filter($this->pluginList, function ($plugin) use
> > ($key) { @@ -72,6 +77,214 @@
> > );
> > }
> >
> > + /**
> > + * Display plugin edit form or process saving changes
> > + *
> > + * @param JitFilter $input
> > + * @return array
> > + * @throws Services_Exception_BadRequest
> > + * @throws Services_Exception_Denied
> > + */
> > + function action_edit($input)
> > + {
> > + global $prefs;
> > +
> > + $parserlib = TikiLib::lib('parser');
> > +
> > + $area_id = $input->area_id->alnumdash();
> > + $type = $input->type->word();
> > + $index = $input->index->int();
> > + $page = $input->page->pagename();
> > + $pluginArgs = $input->pluginArgs->array();
> > + $bodyContent = $input->bodyContent->wikicontent();
> > + $edit_icon = $input->edit_icon->text();
> > + $selectedMod = $input->selectedMod->text();
> > +
> > + $tikilib = TikiLib::lib('tiki');
> > + $pageInfo = $tikilib->get_page_info($page);
> > + if (! $pageInfo) {
> > + // in edit mode
> > + } else {
> > + $perms = $tikilib->get_perm_object($page, 'wiki page', $pageInfo, false);
> > + if ($perms['tiki_p_edit'] !== 'y') {
> > + throw new Services_Exception_Denied(tr('You do not have permission
> to edit "%0"', $page));
> > + }
> > + }
> > +
> > +
> > + if ($_SERVER['REQUEST_METHOD'] === 'POST') {
> > +
> > + $this->action_replace($input);
> > +
> > + return [
> > + 'redirect' => TikiLib::lib('wiki')->sefurl($page),
> > + ];
> > +
> > + } else {        // render the form
> > +
> > + $info = $parserlib->plugin_info($type);
> > + $info['advancedParams'] = [];
> > + $validationRules = [];
> > +
> > + foreach ($info['params'] as $key => $param) {
> > + if ($prefs['feature_jquery_validation'] === 'y') {
> > + // $("#insertItemForm4").validate({rules: { ins_11: { required:
> true}, ins_13: { remote: { url: "validate-ajax.php", type: "post", data: { validator: "distinct", parameter:
> "trackerId=4&fieldId=13&itemId=0", message: "", input: function() { return $("#ins_13").val(); } } } },
> ins_18: { required: true, remote: { url: "validate-ajax.php", type: "post", data: { validator: "distinct",
> parameter: "trackerId=4&fieldId=18&itemId=0", message: "this is not distinct!", input: function() {
> return $("#ins_18").val(); } } } }}, messages: { ins_11: { required: "This field is required" }, ins_18: {
> required: "this is not distinct!" }},
> > + if ($param['required']) {
> > + if (empty($param['parent'])) {
> > + $validationRules["params[$key]"] = ['required'
> => true];
> > + } else {
> > + $validationRules["params[$key]"] =
> ['required_in_group' => [
> > + 1,
> > + '.group-' . $param['parent']['name'],
> > + 'other',
> > + ]];
> > + }
> > + }
> > + }
> > + if (! empty($param['advanced']) && ! isset($pluginArgs[$key]) &&
> empty($param['parent'])) {
> > + $info['advancedParams'][$key] = $param;
> > + unset($info['params'][$key]);
> > + }
> > + }
> > +
> > + if ($validationRules) {
> > + $rules = json_encode(['rules' => $validationRules]);
> > + TikiLib::lib('header')->add_jq_onready('$("#plugin_params >
> form").validate(' . $rules . ');');
> > + }
> > +
> > + if ($type === 'module' && isset($pluginArgs['module'])) {
> > + if ($selectedMod) {
> > + $pluginArgs['module'] = $selectedMod;
> > + }
> > + $file = 'modules/mod-func-' . $pluginArgs['module'] . '.php';
> > + if (file_exists($file)) {
> > + include_once($file);
> > + $info_func = "module_{$pluginArgs['module']}_info";
> > + if (function_exists($info_func)) {
> > + $moduleInfo = $info_func();
> > + if (isset($info['params']['max'])) {
> > + $max = $info['params']['max'];
> > + unset($info['params']['max']); // move "max"
> to last
> > + }
> > + foreach($moduleInfo['params'] as $key => $value) {
> > + $info['params'][$key] = $value;
> > + }
> > + if (! empty($max)) {
> > + $info['params']['max'] = $max;
> > + }
> > + // replace the module plugin description with the one
> from the select module
> > + $info['params']['module']['description'] =
> $moduleInfo['description'];
> > + }
> > +
> > + }
> > + }
> > +
> > + return [
> > + // pass back the input parameters
> > + 'area_id' => $area_id,
> > + 'type' => $type,
> > + 'index' => $index,
> > + 'pageName' => $page,
> > + 'pluginArgs' => $pluginArgs,
> > + 'pluginArgsJSON' => json_encode($pluginArgs),
> > + 'bodyContent' => $bodyContent,
> > + 'edit_icon' => $edit_icon,
> > + 'selectedMod' => $selectedMod,
> > +
> > + 'info' => $info,
> > + 'title' => $type,
> > + ];
> > + }
> > + }
> > +
> > + /**
> > + * Replace plugin in wiki content
> > + * Migrated from tiki-wikiplugin_edit.php
> > + *
> > + * @param JitFilter $input
> > + * @return array
> > + * @throws Services_Exception
> > + * @throws Services_Exception_BadRequest
> > + * @throws Services_Exception_Denied
> > + */
> > + function action_replace($input)
> > + {
> > + global $user;
> > +
> > + $tikilib = TikiLib::lib('tiki');
> > + $parserlib = TikiLib::lib('parser');
> > +
> > + $page = $input->page->pagename();
> > + $type = $input->type->word();
> > + $message = $input->message->text();
> > + $content = $input->content->wikicontent();
> > + $index = $input->index->int();
> > + $params = $input->params->array();
> > +
> > + $referer = $_SERVER['HTTP_REFERER'];
> > +
> > + if (! $page || ! $type || ! $referer || $_SERVER['REQUEST_METHOD'] !== 'POST') {
> > + throw new Services_Exception(tr('Missing parameters'));
> > + }
> > +
> > + $plugin = strtolower($type);
> > + $meta = $parserlib->plugin_info($plugin);
> > +
> > + if (! $page || ! $type || ! $referer) {
> > + throw new Services_Exception(tr('Plugin "%0" not found', $plugin));
> > + }
> > +
> > + if (! $message) {
> > + $message = tr('%0 Plugin modified by editor.', $plugin);
> > + }
> > +
> > + $info = $tikilib->get_page_info($page);
> > + if (! $info) {
> > + throw new Services_Exception_BadRequest(tr('Page "%0" not found', $page));
> > + }
> > +
> > + $perms = $tikilib->get_perm_object($page, 'wiki page', $info, false);
> > + if ($perms['tiki_p_edit'] !== 'y') {
> > + throw new Services_Exception_Denied(tr('You do not have permission to edit
> "%0"', $page));
> > + }
> > +
> > + $current = $info['data'];
> > +
> > + $matches = WikiParser_PluginMatcher::match($current);
> > + $count = 0;
> > + foreach ($matches as $match) {
> > + if ($match->getName() !== $plugin) {
> > + continue;
> > + }
> > +
> > + ++$count;
> > +
> > + if ($index === $count) {
> > + // by using content of "~same~", it will not replace the body that is
> there
> > + $content = ($content == "~same~" ? $match->getBody() : $content);
> > +
> > + if (! $params) {
> > + $params = $match->getArguments();
> > + }
> > +
> > + $match->replaceWithPlugin($plugin, $params, $content);
> > +
> > + $tikilib->update_page(
> > + $page,
> > + $matches->getText(),
> > + $message,
> > + $user,
> > + $tikilib->get_ip_address()
> > + );
> > +
> > + break;
> > + }
> > + }
> > +
> > + return [];
> > +
> > + }
> > +
> > }
> >
> >
> >
> > Modified: trunk/lib/jquery_tiki/tiki-pluginedit.js
> > ===================================================================
> > --- trunk/lib/jquery_tiki/tiki-pluginedit.js 2017-03-13 12:09:36 UTC (rev 61663)
> > +++ trunk/lib/jquery_tiki/tiki-pluginedit.js 2017-03-13 14:58:28 UTC (rev 61664)
> > @@ -82,137 +82,30 @@
> > replaceText = false;
> > }
> > }
> > - var form = build_plugin_form(type, index, pageName, pluginArgs, bodyContent,
> selectedMod);
> >
> > - //with PluginModule, if the user selects another module while the edit form is open
> > - //replace the form with a new one with fields to match the parameters for the module
> selected
> > - $(form).find('tr select[name="params[module]"]').change(function () {
> > - var npluginArgs =
> $.parseJSON($(form).find('input[name="args"][type="hidden"]').val());
> > - //this is the newly selected module
> > - var selectedMod = $(form).find('tr select[name="params[module]"]').val();
> > - $('div.plugin input[name="type"][value="' + type +
> '"]').parent().parent().remove();
> > - popupPluginForm(area_id, type, index, pageName, npluginArgs, bodyContent,
> edit_icon, selectedMod);
> > - });
> > - var $form = $(form).find('tr input[type=submit]').remove();
> > -
> > - container.append(form);
> > -
> > -
> > - var pfc = container.find('table tr').length; // number of rows (plugin form
> contents)
> > - var t = container.find('textarea:visible').length;
> > - if (t) {
> > - pfc += t * 3;
> > - }
> > - if (pfc > 9) {
> > - pfc = 9;
> > - }
> > - if (pfc < 2) {
> > - pfc = 2;
> > - }
> > - pfc = pfc / 10; // factor to scale dialog height
> > -
> > - var $closeBtn = $('<button>')
> > - .text(tr("Close"))
> > - .addClass('btn btn-default')
> > - .click(function () {
> > - $(this).parents(".modal").modal("hide");
> > - });
> > -
> > - var $submitBtn = $('<button>')
> > - .text(replaceText ? tr("Replace") : edit_icon ? tr("Submit") : tr("Insert"))
> > - .addClass('btn btn-primary')
> > - .click(function () {
> > -
> > - $(this).off("click").css("opacity", 0.3);
> > -
> > - var meta = tiki_plugins[type];
> > - var params = [];
> > - var edit = edit_icon;
> > - // whether empty required params exist or not
> > - var emptyRequiredParam = false;
> > -
> > - for (var i = 0; i < form.elements.length; i++) {
> > - var element = form.elements[i].name;
> > -
> > - var matches = element.match(/params\[(.*)\]/);
> > -
> > - if (matches === null) {
> > - // it's not a parameter, skip
> > - continue;
> > - }
> > - var param = matches[1];
> > -
> > - var val = form.elements[i].value;
> > -
> > - // check if fields that are required and visible are not empty
> > - if (meta.params[param]) {
> > - if (meta.params[param].required) {
> > - if (val === '' && $(form.elements[i]).is(':visible'))
> {
> > - $(form.elements[i]).css('border-color',
> 'red');
> > - if
> ($(form.elements[i]).next('.required_param').length === 0) {
> > - $(form.elements[i]).after('<div
> class="required_param" style="font-size: x-small; color: red;">(required)</div>');
> > - }
> > - emptyRequiredParam = true;
> > - }
> > - else {
> > - // remove required feedback if present
> > - $(form.elements[i]).css('border-color',
> '');
> > -
> $(form.elements[i]).next('.required_param').remove();
> > - }
> > - }
> > - }
> > -
> > - if (val !== '') {
> > - if (!edit) {
> > - val = val.replace(/"/g, '\\"'); // escape double
> quotes
> > - }
> > - params.push(param + '="' + val + '"');
> > - }
> > - }
> > -
> > - if (emptyRequiredParam) {
> > - return false;
> > - }
> > -
> > - var blob, pluginContentTextarea = $("[name=content]", form),
> > - pluginContentTextareaEditor =
> syntaxHighlighter.get(pluginContentTextarea);
> > - var cont = (pluginContentTextareaEditor ?
> pluginContentTextareaEditor.getValue() : pluginContentTextarea.val());
> > -
> > - if (meta.body) {
> > - blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' +
> cont + '{' + type.toUpperCase() + '}';
> > - } else {
> > - blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}';
> > - }
> > -
> > - if (edit) {
> > - container.children('form').submit();
> > - // quick and dirty reload
> > - window.location = window.location.href;
> > - } else {
> > - insertAt(area_id, blob, false, false, replaceText);
> > - }
> > - $modal.modal("hide");
> > -
> > - return false;
> > - });
> > -
> > - var heading = container.find('h3').hide();
> > -
> > var $modal = $('.modal.fade:not(.in)').first();
> >
> > - $modal.find(".modal-dialog").empty()
> > - .append($("<div>").addClass("modal-content")
> > - .append($("<div>").addClass("modal-
> header").append($("<h4>").addClass("modal-title").text(heading.text())))
> > - .append($("<div>").addClass("modal-body").append(container))
> > - .append($("<div>").addClass("modal-footer").append($closeBtn,
> $submitBtn))
> > - );
> > + var url = $.service("plugin", "edit", {
> > + area_id: area_id,
> > + type: type,
> > + index: index,
> > + page: pageName,
> > + pluginArgs: pluginArgs,
> > + bodyContent: bodyContent,
> > + edit_icon: edit_icon,
> > + selectedMod: selectedMod ? selectedMod : "",
> > + modal: 1
> > + });
> >
> > // Make the form appear
> > - $modal.modal({
> > - show: false // if it;'s the first time the show.bs.modal
> doesn't trigger sometimes
> > - })
> > - .one('show.bs.modal', function () { // Bind open event
> > + $modal
> > + .modal({
> > + remote: url,
> > + show: false // if it's the first time the show.bs.modal
> doesn't trigger sometimes
> > + })
> > + .one('loaded.bs.modal', function () { // Bind remote loaded
> event
> > handlePluginFieldsHierarchy(type);
> > + handleFormSubmit(this, type, edit_icon, area_id, replaceText);
> > })
> > .modal("show");
> >
> > @@ -231,7 +124,7 @@
> > arguments: arguments,
> > modal: $modal
> > });
> > - }
> > + };
> >
> > /*
> > * Hides all children fields in a wiki-plugin form and @@ -240,14
> > +133,15 @@
> > */
> > function handlePluginFieldsHierarchy(type) {
> > var pluginParams = tiki_plugins[type]['params'];
> > + var $container = $('#plugin_params');
> >
> > var parents = {};
> >
> > $.each(pluginParams, function (paramName, paramValues) {
> > if (paramValues.parent) {
> > - var $parent = $('[name$="params[' + paramValues.parent.name + ']"]',
> '.wikiplugin_edit');
> > + var $parent = $('[name$="params[' + paramValues.parent.name +
> > +']"]', $container);
> >
> > - var $row = $('.wikiplugin_edit').find('#param_' + paramName);
> > + var $row = $container.find('#param_' + paramName);
> > $row.addClass('parent_' + paramValues.parent.name + '_' +
> > paramValues.parent.value);
> >
> > if ($parent.val() !== paramValues.parent.value) { @@ -271,14
> > +165,69 @@
> > $.each(parents, function (parentName, parent) {
> > parent.parentElement.change(function () {
> > $.each(parent.children, function () {
> > - $('.wikiplugin_edit #param_' + this).hide();
> > + $container.find('#param_' + this).hide();
> > });
> > - $('.wikiplugin_edit .parent_' + parentName + '_' + this.value).show();
> > + $container.find('.parent_' + parentName + '_' +
> > +this.value).show();
> > })
> > .change().trigger("chosen:updated");
> > });
> > }
> >
> > + /**
> > + * set up insert/replace button and submit handler in "textarea" edit mode
> > + *
> > + * @param container
> > + * @param type
> > + * @param edit_icon
> > + * @param area_id
> > + */
> > + function handleFormSubmit(container, type, edit_icon, area_id,
> > +replaceText) {
> > +
> > + var meta = tiki_plugins[type], params = [], edit = !!edit_icon,
> > +emptyRequiredParam = false;
> > +
> > + var $form = $("form", container);
> > +
> > + $form.submit(function () {
> > +
> > + if (!process_submit(this)) {
> > + return false;
> > + }
> > +
> > + $(".form-control", $form).each(function () {
> > +
> > + var matches = $(this).attr("name").match(/params\[(.*)\]/),
> > + val = $(this).val();
> > +
> > + if (!matches) {
> > + // it's not a parameter, skip
> > + return;
> > + }
> > +
> > + if (val&& !edit) {
> > + val = val.replace(/"/g, '\\"'); // escape double quotes
> > + params.push(matches[1] + '="' + val + '"');
> > + }
> > + });
> > +
> > + var blob, pluginContentTextarea = $("[name=content]", $form),
> > + pluginContentTextareaEditor =
> syntaxHighlighter.get(pluginContentTextarea),
> > + cont = (pluginContentTextareaEditor ?
> > +pluginContentTextareaEditor.getValue() :
> > +pluginContentTextarea.val());
> > +
> > + if (!edit) {
> > + if (meta.body) {
> > + blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' +
> cont + '{' + type.toUpperCase() + '}';
> > + } else {
> > + blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}';
> > + }
> > +
> > + insertAt(area_id, blob, false, false, replaceText);
> > + $(container).modal("hide");
> > +
> > + return false;
> > + }
> > + });
> > + }
> > +
> > function dialogSelectElement(area_id, elementStart, elementEnd) {
> > if (typeof CKEDITOR !== 'undefined' && typeof CKEDITOR.instances[area_id] !==
> 'undefined') {
> > return;
> > @@ -317,325 +266,4 @@
> >
> > }
> >
> > -
> > - function build_plugin_form(type, index, pageName, pluginArgs, bodyContent, selectedMod) {
> > - var form = document.createElement('form');
> > - form.method = 'post';
> > - form.action = 'tiki-wikiplugin_edit.php';
> > - form.className = 'wikiplugin_edit';
> > -
> > - var hiddenPage = document.createElement('input');
> > - hiddenPage.type = 'hidden';
> > - hiddenPage.name = 'page';
> > - hiddenPage.value = pageName;
> > - form.appendChild(hiddenPage);
> > -
> > - var hiddenType = document.createElement('input');
> > - hiddenType.type = 'hidden';
> > - hiddenType.name = 'type';
> > - hiddenType.value = type;
> > - form.appendChild(hiddenType);
> > -
> > - var hiddenIndex = document.createElement('input');
> > - hiddenIndex.type = 'hidden';
> > - hiddenIndex.name = 'index';
> > - hiddenIndex.value = index;
> > - form.appendChild(hiddenIndex);
> > -
> > - //
> > - var savedArgs = document.createElement('input');
> > - savedArgs.type = 'hidden';
> > - savedArgs.name = 'args';
> > - savedArgs.value = $.toJSON(pluginArgs);
> > - form.appendChild(savedArgs);
> > -
> > - //Convert to JSON and then back to an object to break
> > - //link between meta local variable and tiki_plugins[type] global variable.
> > - //Otherwise each change to meta.params using the extend below was being
> appended to the global
> > - //Probably a much easier way to do this
> > - var infostring = $.toJSON(tiki_plugins[type]);
> > - var meta = $.parseJSON(infostring);
> > -
> > - //For PluginModule, add selected module parameters to the plugin edit form
> > - if (type == 'module') {
> > - //isolate the module parameter object so it will be shown first in the form
> > - var onlymod = {"params": {"module": meta.params.module}};
> > - //user has not changed the module selection since opening the form
> > - if (typeof selectedMod == 'undefined') {
> > - //pick up the parameters of the saved module parameter
> > - if (typeof pluginArgs.module != 'undefined') {
> > - //this orders the module parameter first, module related
> parameters second, other PluginModule parameters besides module last
> > - meta.params = $.extend(onlymod.params,
> tiki_module_params[pluginArgs.module].params, meta.params);
> > - //Use the module description
> > - meta.params.module.description =
> tiki_module_params[pluginArgs.module].description;
> > - //otherwise pick up the parameters of the first module option
> since that will be selected automatically
> > - } else {
> > - meta.params = $.extend(onlymod.params,
> tiki_module_params[meta.params.module.options[0].value].params, meta.params);
> > - meta.params.module.description =
> tiki_module_params[meta.params.module.options[0].value].description;
> > - }
> > - //user has selected another module while the form was open - pick up
> parameters for the selected module
> > - } else if (tiki_module_params[selectedMod] != null) {
> > - meta.params = $.extend(onlymod.params,
> tiki_module_params[selectedMod].params, meta.params);
> > - meta.params.module.description =
> tiki_module_params[selectedMod].description;
> > - }
> > - }
> > -
> > - var header = document.createElement('h3');
> > - header.innerHTML = meta.name;
> > - form.appendChild(header);
> > -
> > - var desc = document.createElement('div');
> > - desc.innerHTML = meta.description;
> > - if (meta.documentation && jqueryTiki.helpurl) {
> > - desc.innerHTML += ' <a href="' + jqueryTiki.helpurl + meta.documentation + '"
> target="tikihelp" class="tikihelp" tabIndex="-1" title="' + tr('Help') + '">' +
> > - '<span class="icon icon-help fa fa-question-circle fa-fw"></span>' +
> > - '</a>';
> > -
> > - }
> > - form.appendChild(desc);
> > -
> > - var table = document.createElement('table'), param;
> > - table.className = 'table';
> > - table.id = 'plugin_params';
> > - form.appendChild(table);
> > -
> > - for (param in meta.params) {
> > - if (meta.params[param].advanced) {
> > - var br = document.createElement('br');
> > - form.appendChild(br);
> > -
> > - var span_advanced_button = document.createElement('span');
> > - span_advanced_button.className = 'button';
> > - form.appendChild(span_advanced_button);
> > -
> > - var advanced_button = document.createElement('a');
> > - advanced_button.innerHTML = tr('Advanced options');
> > - advanced_button.onclick = function () {
> > - flip('plugin_params_advanced');
> > - };
> > - span_advanced_button.appendChild(advanced_button);
> > -
> > - var table_advanced = document.createElement('table');
> > - table_advanced.className = 'normal';
> > - table_advanced.style.display = 'none';
> > - table_advanced.id = 'plugin_params_advanced';
> > - form.appendChild(table_advanced);
> > -
> > - break;
> > - }
> > - }
> > -
> > - var potentiallyExtraPluginArgs = pluginArgs, extraArg;
> > -
> > - var rowNumber = 0;
> > - var rowNumberAdvanced = 0;
> > - for (param in meta.params) {
> > - if (typeof(meta.params[param]) != 'object' || meta.params[param].name ==
> 'array') {
> > - continue;
> > - }
> > -
> > - var row;
> > - if (meta.params[param].advanced && !meta.params[param].required &&
> typeof pluginArgs[param] === "undefined") {
> > - row = table_advanced.insertRow(rowNumberAdvanced++);
> > - } else {
> > - row = table.insertRow(rowNumber++);
> > - }
> > - var value = pluginArgs.length < 1 ? '' : pluginArgs[param];// for param like sort
> > - //for use with PluginModule to identify saved module parameter value
> > - var nsavedArgs =
> $.parseJSON($(form).find('input[name="args"][type="hidden"]').val());
> > - //last two parameters (selectedMod and savedArgs are only needed for
> PluginModule
> > - build_plugin_form_row(row, param, meta.params[param].name,
> meta.params[param].required, value, meta.params[param].description, meta.params[param],
> selectedMod, nsavedArgs);
> > -
> > - delete potentiallyExtraPluginArgs[param];
> > - }
> > -
> > - for (extraArg in potentiallyExtraPluginArgs) {
> > - if (extraArg === '') {
> > - // TODO HACK: See bug 2499 http://dev.tiki.org/tiki-
> view_tracker_item.php?itemId=2499
> > - continue;
> > - }
> > -
> > - row = table.insertRow(rowNumber++);
> > - build_plugin_form_row(row, extraArg, extraArg, 'extra', pluginArgs[extraArg],
> extraArg);
> > - }
> > -
> > - var bodyRow = table.insertRow(rowNumber++);
> > - var bodyCell = bodyRow.insertCell(0);
> > - var bodyField = document.createElement('textarea');
> > - bodyField.rows = '12';
> > - bodyField.className = 'form-control';
> > - var bodyDesc = document.createElement('div');
> > -
> > - if (meta.body) {
> > - bodyDesc.innerHTML = meta.body;
> > - } else {
> > - bodyRow.style.display = 'none';
> > - }
> > - bodyField.name = 'content';
> > - bodyField.value = bodyContent;
> > -
> > - bodyRow.className = 'formcolor';
> > -
> > - bodyCell.appendChild(bodyDesc);
> > - bodyCell.appendChild(bodyField);
> > - bodyCell.colSpan = '2';
> > -
> > - var submitRow = table.insertRow(rowNumber++);
> > - var submitCell = submitRow.insertCell(0);
> > - var submit = document.createElement('input');
> > -
> > - submit.type = 'submit';
> > - submitCell.colSpan = 2;
> > - submitCell.appendChild(submit);
> > - submitCell.className = 'submit';
> > -
> > - return form;
> > - }
> > -
> > -//last two parameters (selectedMod and savedArgs are only needed for PluginModule
> > - function build_plugin_form_row(row, name, label_name, requiredOrSpecial, value,
> description, paramDef, selectedMod, savedArgs) {
> > -
> > - var label = row.insertCell(0);
> > - var field = row.insertCell(1);
> > - row.className = 'form-group';
> > - row.id = 'param_' + name;
> > -
> > - label.innerHTML = label_name;
> > - label.className = 'col-sm-3';
> > - field.className = 'col-sm-9';
> > - switch (requiredOrSpecial) {
> > - case (true):  // required flag
> > - label.style.fontWeight = 'bold';
> > - break;
> > - case ('extra') :
> > - label.style.fontStyle = 'italic';
> > - }
> > -
> > - var input, icon;
> > - if (paramDef && paramDef.options) {
> > - input = document.createElement('select');
> > - input.name = 'params[' + name + ']';
> > - input.className = 'form-control';
> > - for (var o = 0; o < paramDef.options.length; o++) {
> > - var opt = document.createElement('option');
> > - opt.value = paramDef.options[o].value;
> > - var opt_text = document.createTextNode(paramDef.options[o].text);
> > - opt.appendChild(opt_text);
> > - //either not PluginModule or user has not changed module selection,
> so use saved value
> > - if (typeof selectedMod == 'undefined') {
> > - if (value && opt.value == value) {
> > - opt.selected = true;
> > - }
> > - } else {
> > - //user changed module selection in PluginModule
> > - if (selectedMod == opt.value) {
> > - opt.selected = true;
> > - } else if (savedArgs.module == opt.value) {
> > - //use later to display saved module parameter value
> > - var savedtext = opt.innerHTML;
> > - opt.style.fontWeight = 'bold';
> > - opt.innerHTML = opt.innerHTML + '  -- ' + tr('saved
> value');
> > - }
> > - }
> > - input.appendChild(opt);
> > - }
> > - } else {
> > - input = document.createElement('input');
> > - input.className = 'form-control';
> > - input.type = 'text';
> > - input.name = 'params[' + name + ']';
> > - if (value) {
> > - input.value = value.replace(/\\"/g, '"'); // unescape quotes
> > - }
> > - }
> > -
> > - field.appendChild(input);
> > - if (paramDef && paramDef.type == 'image') {
> > - icon = document.createElement('img');
> > - icon.src = 'img/icons/image.png';
> > - input.id = paramDef.area ? paramDef.area : 'fgal_picker';
> > - icon.onclick = function () {
> > - openFgalsWindowArea(paramDef.area ? paramDef.area :
> 'fgal_picker');
> > - };
> > - field.appendChild(icon);
> > - } else if (paramDef && paramDef.type == 'fileId') {
> > - var help = document.createElement('span');
> > - input.id = paramDef.area ? paramDef.area : 'fgal_picker';
> > - help.onclick = function () {
> > - openFgalsWindowArea(paramDef.area ? paramDef.area :
> 'fgal_picker');
> > - };
> > - help.innerHTML = " <a href='#'>" + tr('Pick a file.') + "</a>";
> > - field.appendChild(help);
> > - } else if (paramDef && paramDef.type == 'kaltura') {
> > - input.id = paramDef.area;
> > - var img = $("<img />")
> > - .attr("src", paramDef.icon)
> > - .addClass("icon")
> > - .css("cursor", "pointer")
> > - .attr("title", tr("Upload or record media"))
> > - ;
> > - $(field).append(
> > - $('<a/>')
> > - .attr('href', $.service('kaltura', 'upload'))
> > - .append(img)
> > - .click(function () {
> > - $(this).serviceDialog({
> > - title: tr("Upload or record media"),
> > - width: 710,
> > - height: 450,
> > - hideButtons: true,
> > - success: function (data) {
> > - if (data.entries) {
> > - input.value = data.entries[0];
> > - }
> > - }
> > - });
> > - return false;
> > - })
> > - );
> > - }
> > -
> > - if (description) {
> > - var desc = document.createElement('div');
> > - desc.style.fontSize = 'x-small';
> > - desc.innerHTML = description;
> > - field.appendChild(desc);
> > - }
> > - if (paramDef && paramDef.accepted) {
> > - $(field).append(
> > - $("<div>")
> > - .css("fontSize", "x-small")
> > - .html("<strong>" + tr("Accepted:") + "</strong><br>" +
> paramDef.accepted)[0]
> > - );
> > - }
> > - //in PluginModule, show saved nodule parameter value if user has changed selection
> > - //since the form changes to match the newly selected module, it's useful to show the
> > - //saved module parameter so the user can go back to it
> > - if (typeof savedtext != 'undefined') {
> > - var saved = document.createElement('div');
> > - saved.style.fontSize = 'x-small';
> > - saved.style.fontStyle = 'italic';
> > - saved.style.fontWeight = 'bold';
> > - saved.innerHTML = tr('Saved value:') + ' ' + savedtext;
> > - field.appendChild(saved);
> > - }
> > -
> > - if (paramDef && paramDef.filter) {
> > - if (paramDef.filter == "pagename") {
> > - $(input).tiki("autocomplete", "pagename");
> > - } else if (paramDef.filter == "groupname") {
> > - $(input).tiki("autocomplete", "groupname", {multiple: true,
> multipleSeparator: "|"});
> > - } else if (paramDef.filter == "username") {
> > - $(input).tiki("autocomplete", "username", {multiple: true,
> multipleSeparator: "|"});
> > - } else if (paramDef.filter == "date") {
> > - $(input).tiki("datepicker");
> > - }
> > - }
> > -
> > - }
> > -
> > - function openFgalsWindowArea(area) {
> > - openFgalsWindow('tiki-list_file_gallery.php?filegals_manager=' + area + '&galleryId=' +
> jqueryTiki.home_file_gallery, true); // reload
> > - }
> > -
> > })(jQuery);
> >
> > Copied: trunk/templates/plugin/edit.tpl (from rev 61597,
> > trunk/templates/plugin/list.tpl)
> ===================================================================
> > --- trunk/templates/plugin/edit.tpl                        (rev 0)
> > +++ trunk/templates/plugin/edit.tpl 2017-03-13 14:58:28 UTC (rev 61664)
> > @@ -0,0 +1,116 @@
> > +{extends 'layout_view.tpl'}
> > +
> > +{block name="title"}
> > + <h3>{$title}</h3>
> > +{/block}
> > +
> > +{block name="content"}
> > + {function plugin_edit_row}{* needs to be in the same block it seems? *}
> > + {if
> $param.area}{$inputId=$param.area|escape}{else}{$inputId="param_{$name|escape}_input"}{/if}
> > + <div  class="col-sm-3">
> > + <label for="{$inputId}">{$param.name|escape}</label>
> > + {if not empty($param.type)}
> > + {$onclick = "openFgalsWindow('{$prefs.home_file_gallery|sefurl:'file
> gallery':true}filegals_manager={$param.area|escape}&id=1', true);return false;"}
> > + {if $param.type eq 'image'}
> > + <br>{icon name='image' title='{tr}Select image{/tr}'
> onclick=$onclick class='btn btn-xs btn-default'}
> > + {elseif $param.type eq 'fileId'}
> > + <br>{icon name='file' title='{tr}Pick a file{/tr}' onclick=$onclick
> class='btn btn-xs btn-default'}
> > + {elseif $param.type eq 'kaltura'}
> > + {jq}
> > +$("#picker_{{$name|escape}}").parent().click(function () {
> > + $(this).serviceDialog({
> > + title: tr("Upload or record media"),
> > + width: 710,
> > + height: 450,
> > + hideButtons: true,
> > + success: function (data) {
> > + if (data.entries) {
> > + input.value = data.entries[0];
> > + }
> > + }
> > + });
> > + return false;
> > +});
> > + {/jq}
> > + <br>{icon name='video' title='{tr}Upload or record media{/tr}'
> href={service controller='kaltura' action='upload'} id='picker_'|cat:$name|escape class='btn btn-xs
> btn-default'}
> > + {/if}
> > + {/if}
> > + </div>
> > + <div class="col-sm-9">
> > + {if (not empty($param.parent.name))}
> > + {$groupClass = " group-`$param.parent.name`"}
> > + {else}
> > + {$groupClass = ''}
> > + {/if}
> > + {if empty($param.options)}
> > + <input value="{if isset($pluginArgs[$name])}{$pluginArgs[$name]}{/if}"
> class="form-control{$groupClass}" id="{$inputId}" type="text" name="params[{$name|escape}]">
> > + {if not empty($param.filter)}
> > + {if $param.filter eq "pagename"}
> > + {jq}$({{$inputId}}).tiki("autocomplete",
> "pagename");{/jq}
> > + {elseif $param.filter eq "groupname"}
> > + {jq}$({{$inputId}}).tiki("autocomplete", "groupname",
> {multiple: true, multipleSeparator: "|"});{/jq}
> > + {elseif $param.filter eq "username"}
> > + {jq}$({{$inputId}}).tiki("autocomplete", "username",
> {multiple: true, multipleSeparator: "|"});{/jq}
> > + {elseif $param.filter eq "date"}
> > + {jq}$({{$inputId}}).tiki("datepicker");{/jq}
> > + {/if}
> > + {/if}
> > +
> > + {else}
> > + <select class="form-control{$groupClass}" type="text"
> name="params[{$name|escape}]" id="{$inputId}">
> > + {foreach $param.options as $option}
> > + <option value="{$option.value|escape}" {if
> isset($pluginArgs[$name]) and $pluginArgs[$name] eq $option.value} selected="selected"{/if}>
> > + {$option.text|escape}
> > + </option>
> > + {/foreach}
> > + </select>
> > + {/if}
> > + <div class="description">{$param.description}</div>
> > + </div>
> > + {/function}
> > + <div class="form-horizontal" id="plugin_params">
> > + <form action="{service controller='plugin' action='edit'}" method="post">
> > + {foreach $info.params as $name => $param}
> > + <div class="form-group{if $param.advanced} advanced{/if}"
> id="param_{$name|escape}">
> > + {plugin_edit_row param=$param name=$name info=$info
> pluginArgs=$pluginArgs}
> > + </div>
> > + {/foreach}
> > + {if not empty($info.advancedParams)}
> > + {button _text='Advanced' _onclick="$('.form-
> group.advanced.default').toggle('fast'); return false;" _class='btn btn-xs margin-bottom-md'}
> > + {foreach $info.advancedParams as $name => $param}
> > + <div class="form-group advanced default" style="display:
> none;">
> > + {plugin_edit_row param=$param name=$name
> info=$info pluginArgs=$pluginArgs}
> > + </div>
> > + {/foreach}
> > + {/if}
> > +
> > + <div class="form-group"{if empty($info.body)} style="display:none"{/if}>
> > + <label for="content" class="col-sm-3">{tr}Body{/tr}</label>
> > + <div class="col-sm-9">
> > + <textarea name="content" id="content" class="form-
> control">{$bodyContent|escape}</textarea>
> > + <div class="description">{$info.body}</div>
> > + </div>
> > + </div>
> > +
> > + <div class="submit">
> > + <input type="hidden" name="page" value="{$pageName}">
> > + <input type="hidden" name="type" value="{$type}">
> > + <input type="hidden" name="index" value="{$index}">
> > + <input type="hidden" name="args" value="{$pluginArgsJSON}">
> > + <input type="submit" class="btn btn-primary" value="{tr}Save{/tr}">
> > + </div>
> > +
> > + {if $type eq 'module'}
> > + {jq}$("#param_module_input").change(function () {
> > + var selectMod = $(this).val();
> > + $.closeModal();
> > + $(document).one("hidden.bs.modal", function () {
> > + popupPluginForm("{{$area_id}}","{{$type}}",
> {{$index}}, "{{$pageName}}", {{$pluginArgsJSON}}, "{{$bodyContent}}", "{{$edit_icon}}", selectMod);
> > + });
> > + });{/jq}
> > + {/if}
> > +
> > + </form>
> > + </div>
> > +{/block}
> > +
> >
> > Modified: trunk/tiki-wikiplugin_edit.php
> > ===================================================================
> > --- trunk/tiki-wikiplugin_edit.php 2017-03-13 12:09:36 UTC (rev 61663)
> > +++ trunk/tiki-wikiplugin_edit.php 2017-03-13 14:58:28 UTC (rev 61664)
> > @@ -10,62 +10,9 @@
> >
> > require 'tiki-setup.php';
> >
> > -if ( ! isset( $_POST['page'], $_POST['content'], $_POST['index'], $_POST['type'],
> $_SERVER['HTTP_REFERER'] ) )
> > - die( 'Missing parameters' );
> > +trigger_error(tr('Note, deprecated file tiki-wikiplugin_edit.php,
> > +code moved to service plugin->replace'));
> >
> > -$page = $_POST['page'];
> > +TikiLib::lib('service')->render('plugin', 'replace', $jitPost);
> >
> > -$plugin = strtolower(basename($_POST['type']));
> > -$type = TikiLib::strtoupper($plugin);
> > -
> > -if (empty($parserlib)) {
> > - $parserlib = TikiLib::lib('parser');
> > -}
> > -
> > -if ( ! $meta = $parserlib->plugin_info($plugin) )
> > - exit;
> > -
> > -if ( ! isset( $_POST['message'] ) )
> > - $_POST['message'] = (isset($meta['name']) ? tra($meta['name']) : $plugin) . ' ' . tra('Plugin
> modified by editor.');
> > -
> > -$info = $tikilib->get_page_info($page);
> > -$tikilib->get_perm_object($page, 'wiki page', $info, true); -if
> > ($tiki_p_edit != 'y') {
> > - header("Location: {$_SERVER['HTTP_REFERER']}");
> > - exit;
> > -}
> > -$content = $_POST['content'];
> > -$current = $info['data'];
> > -
> > -$matches = WikiParser_PluginMatcher::match($current);
> > -$count = 0;
> > -foreach ( $matches as $match ) {
> > - if ( $match->getName() !== $plugin ) {
> > - continue;
> > - }
> > -
> > - ++$count;
> > -
> > - if ( $_POST['index'] == $count ) {
> > - //by using content of "~same~", it will not replace the body that is there
> > - $content = ($content == "~same~" ? $match->getBody() : $content);
> > - $params = $match->getArguments();
> > -
> > - // If parameters are provided, rebuild the parameter line
> > - if ( isset( $_POST['params'] ) && is_array($_POST['params']) ) {
> > - // $values was relaxed to accept any argument rather than those defined up
> front
> > - // in the plugin's parameter list. This facilitates the use of modules as plugins.
> > - $params = $_POST['params'];
> > - }
> > -
> > - $match->replaceWithPlugin($plugin, $params, $content);
> > -
> > - $parsed = $matches->getText();
> > -
> > - $tikilib->update_page($page, $parsed, $_POST['message'], $user, $tikilib-
> >get_ip_address());
> > - break;
> > - }
> > -}
> > -
> > header("Location: {$_SERVER['HTTP_REFERER']}"); exit;
> >
> > This was sent by the SourceForge.net collaborative development platform, the world's largest Open
> Source development site.
> >
> >
> > ----------------------------------------------------------------------
> > -------- Check out the vibrant tech community on one of the world's
> > most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> > _______________________________________________
> > Tikiwiki-cvs mailing list
> > [hidden email]
> > https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
> >
>
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org!
> http://sdm.link/slashdot _______________________________________________
> TikiWiki-devel mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
TikiWiki-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]

Jonny Bradley-4
Hi Chealer,

The comment about the block thing was that the function definition (on the same line as the comment) needs to be in the same block as where it is called from, which is the block starting one line above the function definition start - i just thought a comment there might save someone else the hour or so i spent trying to work out why it wasn't working ;) I guess that failed...

Yes, it may well have disrupted user habits - it wasn't necessarily an ENHancement as most users were probably happy with the javascript only plugin edit popups we've had for ages, and it wasn't really a FIX... what would you have tagged it as? (to be honest, i don't spend too long choosing commit tags)

Thanks for the escapes added to the edit.tpl file, sorry i missed those - could you backport it to 17.x please? Otherwise we'll probably get conflicts (and yes, that args param is probably redundant)

jonny




> On 4 Apr 2017, at 17:19, Cloutier, Philippe (RESSOURCE EXTERNE) <[hidden email]> wrote:
>
> Thank you very much Jonny,
> I do not understand your edit.tpl comment {* needs to be in the same block it seems? *} (what needs to be in the same block as what?).
>
> I also do not understand why the commit message has [MOD]. Could this disrupt user habits significantly?
>
>> -----Message d'origine-----
>> De : Jonny Bradley [mailto:[hidden email]]
>> Envoyé : 13 mars 2017 11:12
>> À : Tiki developers <[hidden email]>
>> Objet : [Tiki-devel] pluginedit refactoring [was Re: [Tikiwiki-cvs/svn] SF.net SVN: tikiwiki:[61664] trunk]
>>
>> Hi all
>>
>> This is a quite big change for Tiki 17, and really quite overdue and needed for the list plugin GUI, which
>> i'm hoping now to add before we branch (for which thank you Marc!)
>>
>> Plugin edit forms are now created sever-side so we can use a template (templates/plugin/edit.tpl) to
>> build the form and all the goodness of a php service lib/core/Services/Edit/PluginController.php for
>> processing it. Rather than re-creating the ancient custom js validation i've used the jquery validator (if
>> the feature is enabled) which i think works better and will be more useful in the future.
>>
>> In the future we should be able to extend this method for editing plugins to other objects, not just
>> wiki pages.
>>
>> Anyway, as with many of these big changes there isn't a huge amount to see that's new (yet) and
>> something somewhere is bound to have borken so please do let me know if you find anything related
>> to this that's fallen off!
>>
>> Thanks,
>>
>> jonny
>>
>>
>>
>>
>>> On 13 Mar 2017, at 14:58, [hidden email] wrote:
>>>
>>> Revision: 61664
>>>         http://sourceforge.net/p/tikiwiki/code/61664
>>> Author:   jonnybradley
>>> Date:     2017-03-13 14:58:28 +0000 (Mon, 13 Mar 2017)
>>> Log Message:
>>> -----------
>>> [MOD] plugins: Move plugin edit form processing to a serverside AJAX service.
>>> TODO Switch over remaining usages of tiki-wikiplugin_edit.php to
>>> service plugin replace and remove that and tiki*js.php files Probably
>>> further tidying up and fixes to do too, please advice of any breakages
>>> (thanks marcalporte)
>>>
>>> Modified Paths:
>>> --------------
>>>   trunk/lib/core/Services/Edit/PluginController.php
>>>   trunk/lib/jquery_tiki/tiki-pluginedit.js
>>>   trunk/tiki-wikiplugin_edit.php
>>>
>>> Added Paths:
>>> -----------
>>>   trunk/templates/plugin/edit.tpl
>>>
>>> Modified: trunk/lib/core/Services/Edit/PluginController.php
>>> ===================================================================
>>> --- trunk/lib/core/Services/Edit/PluginController.php 2017-03-13 12:09:36 UTC (rev 61663)
>>> +++ trunk/lib/core/Services/Edit/PluginController.php 2017-03-13 14:58:28 UTC (rev 61664)
>>> @@ -17,7 +17,7 @@
>>>
>>> function __construct()
>>> {
>>> - $this->parserlib = TikiLib::lib('parser');
>>> + $this->pluginList = [];
>>> }
>>>
>>> function setUp()
>>> @@ -27,7 +27,12 @@
>>> $this->pluginList = TikiLib::lib('wiki')->list_plugins(true);
>>> }
>>>
>>> -
>>> + /**
>>> + * List all or some of theplugins for the textarea control panel
>>> + *
>>> + * @param JitFilter $input
>>> + * @return array
>>> + */
>>> function action_list($input)
>>> {
>>> $filter = $input->filter->text();
>>> @@ -41,7 +46,7 @@
>>> }
>>> $results = TikiLib::lib('prefs')->getMatchingPreferences($query);
>>>
>>> - foreach($results as $result) {
>>> + foreach ($results as $result) {
>>> if (strpos($result, 'wikiplugin_') === 0) {
>>> $key = strtoupper(substr($result, 11));
>>> $arr = array_filter($this->pluginList, function ($plugin) use
>>> ($key) { @@ -72,6 +77,214 @@
>>> );
>>> }
>>>
>>> + /**
>>> + * Display plugin edit form or process saving changes
>>> + *
>>> + * @param JitFilter $input
>>> + * @return array
>>> + * @throws Services_Exception_BadRequest
>>> + * @throws Services_Exception_Denied
>>> + */
>>> + function action_edit($input)
>>> + {
>>> + global $prefs;
>>> +
>>> + $parserlib = TikiLib::lib('parser');
>>> +
>>> + $area_id = $input->area_id->alnumdash();
>>> + $type = $input->type->word();
>>> + $index = $input->index->int();
>>> + $page = $input->page->pagename();
>>> + $pluginArgs = $input->pluginArgs->array();
>>> + $bodyContent = $input->bodyContent->wikicontent();
>>> + $edit_icon = $input->edit_icon->text();
>>> + $selectedMod = $input->selectedMod->text();
>>> +
>>> + $tikilib = TikiLib::lib('tiki');
>>> + $pageInfo = $tikilib->get_page_info($page);
>>> + if (! $pageInfo) {
>>> + // in edit mode
>>> + } else {
>>> + $perms = $tikilib->get_perm_object($page, 'wiki page', $pageInfo, false);
>>> + if ($perms['tiki_p_edit'] !== 'y') {
>>> + throw new Services_Exception_Denied(tr('You do not have permission
>> to edit "%0"', $page));
>>> + }
>>> + }
>>> +
>>> +
>>> + if ($_SERVER['REQUEST_METHOD'] === 'POST') {
>>> +
>>> + $this->action_replace($input);
>>> +
>>> + return [
>>> + 'redirect' => TikiLib::lib('wiki')->sefurl($page),
>>> + ];
>>> +
>>> + } else {        // render the form
>>> +
>>> + $info = $parserlib->plugin_info($type);
>>> + $info['advancedParams'] = [];
>>> + $validationRules = [];
>>> +
>>> + foreach ($info['params'] as $key => $param) {
>>> + if ($prefs['feature_jquery_validation'] === 'y') {
>>> + // $("#insertItemForm4").validate({rules: { ins_11: { required:
>> true}, ins_13: { remote: { url: "validate-ajax.php", type: "post", data: { validator: "distinct", parameter:
>> "trackerId=4&fieldId=13&itemId=0", message: "", input: function() { return $("#ins_13").val(); } } } },
>> ins_18: { required: true, remote: { url: "validate-ajax.php", type: "post", data: { validator: "distinct",
>> parameter: "trackerId=4&fieldId=18&itemId=0", message: "this is not distinct!", input: function() {
>> return $("#ins_18").val(); } } } }}, messages: { ins_11: { required: "This field is required" }, ins_18: {
>> required: "this is not distinct!" }},
>>> + if ($param['required']) {
>>> + if (empty($param['parent'])) {
>>> + $validationRules["params[$key]"] = ['required'
>> => true];
>>> + } else {
>>> + $validationRules["params[$key]"] =
>> ['required_in_group' => [
>>> + 1,
>>> + '.group-' . $param['parent']['name'],
>>> + 'other',
>>> + ]];
>>> + }
>>> + }
>>> + }
>>> + if (! empty($param['advanced']) && ! isset($pluginArgs[$key]) &&
>> empty($param['parent'])) {
>>> + $info['advancedParams'][$key] = $param;
>>> + unset($info['params'][$key]);
>>> + }
>>> + }
>>> +
>>> + if ($validationRules) {
>>> + $rules = json_encode(['rules' => $validationRules]);
>>> + TikiLib::lib('header')->add_jq_onready('$("#plugin_params >
>> form").validate(' . $rules . ');');
>>> + }
>>> +
>>> + if ($type === 'module' && isset($pluginArgs['module'])) {
>>> + if ($selectedMod) {
>>> + $pluginArgs['module'] = $selectedMod;
>>> + }
>>> + $file = 'modules/mod-func-' . $pluginArgs['module'] . '.php';
>>> + if (file_exists($file)) {
>>> + include_once($file);
>>> + $info_func = "module_{$pluginArgs['module']}_info";
>>> + if (function_exists($info_func)) {
>>> + $moduleInfo = $info_func();
>>> + if (isset($info['params']['max'])) {
>>> + $max = $info['params']['max'];
>>> + unset($info['params']['max']); // move "max"
>> to last
>>> + }
>>> + foreach($moduleInfo['params'] as $key => $value) {
>>> + $info['params'][$key] = $value;
>>> + }
>>> + if (! empty($max)) {
>>> + $info['params']['max'] = $max;
>>> + }
>>> + // replace the module plugin description with the one
>> from the select module
>>> + $info['params']['module']['description'] =
>> $moduleInfo['description'];
>>> + }
>>> +
>>> + }
>>> + }
>>> +
>>> + return [
>>> + // pass back the input parameters
>>> + 'area_id' => $area_id,
>>> + 'type' => $type,
>>> + 'index' => $index,
>>> + 'pageName' => $page,
>>> + 'pluginArgs' => $pluginArgs,
>>> + 'pluginArgsJSON' => json_encode($pluginArgs),
>>> + 'bodyContent' => $bodyContent,
>>> + 'edit_icon' => $edit_icon,
>>> + 'selectedMod' => $selectedMod,
>>> +
>>> + 'info' => $info,
>>> + 'title' => $type,
>>> + ];
>>> + }
>>> + }
>>> +
>>> + /**
>>> + * Replace plugin in wiki content
>>> + * Migrated from tiki-wikiplugin_edit.php
>>> + *
>>> + * @param JitFilter $input
>>> + * @return array
>>> + * @throws Services_Exception
>>> + * @throws Services_Exception_BadRequest
>>> + * @throws Services_Exception_Denied
>>> + */
>>> + function action_replace($input)
>>> + {
>>> + global $user;
>>> +
>>> + $tikilib = TikiLib::lib('tiki');
>>> + $parserlib = TikiLib::lib('parser');
>>> +
>>> + $page = $input->page->pagename();
>>> + $type = $input->type->word();
>>> + $message = $input->message->text();
>>> + $content = $input->content->wikicontent();
>>> + $index = $input->index->int();
>>> + $params = $input->params->array();
>>> +
>>> + $referer = $_SERVER['HTTP_REFERER'];
>>> +
>>> + if (! $page || ! $type || ! $referer || $_SERVER['REQUEST_METHOD'] !== 'POST') {
>>> + throw new Services_Exception(tr('Missing parameters'));
>>> + }
>>> +
>>> + $plugin = strtolower($type);
>>> + $meta = $parserlib->plugin_info($plugin);
>>> +
>>> + if (! $page || ! $type || ! $referer) {
>>> + throw new Services_Exception(tr('Plugin "%0" not found', $plugin));
>>> + }
>>> +
>>> + if (! $message) {
>>> + $message = tr('%0 Plugin modified by editor.', $plugin);
>>> + }
>>> +
>>> + $info = $tikilib->get_page_info($page);
>>> + if (! $info) {
>>> + throw new Services_Exception_BadRequest(tr('Page "%0" not found', $page));
>>> + }
>>> +
>>> + $perms = $tikilib->get_perm_object($page, 'wiki page', $info, false);
>>> + if ($perms['tiki_p_edit'] !== 'y') {
>>> + throw new Services_Exception_Denied(tr('You do not have permission to edit
>> "%0"', $page));
>>> + }
>>> +
>>> + $current = $info['data'];
>>> +
>>> + $matches = WikiParser_PluginMatcher::match($current);
>>> + $count = 0;
>>> + foreach ($matches as $match) {
>>> + if ($match->getName() !== $plugin) {
>>> + continue;
>>> + }
>>> +
>>> + ++$count;
>>> +
>>> + if ($index === $count) {
>>> + // by using content of "~same~", it will not replace the body that is
>> there
>>> + $content = ($content == "~same~" ? $match->getBody() : $content);
>>> +
>>> + if (! $params) {
>>> + $params = $match->getArguments();
>>> + }
>>> +
>>> + $match->replaceWithPlugin($plugin, $params, $content);
>>> +
>>> + $tikilib->update_page(
>>> + $page,
>>> + $matches->getText(),
>>> + $message,
>>> + $user,
>>> + $tikilib->get_ip_address()
>>> + );
>>> +
>>> + break;
>>> + }
>>> + }
>>> +
>>> + return [];
>>> +
>>> + }
>>> +
>>> }
>>>
>>>
>>>
>>> Modified: trunk/lib/jquery_tiki/tiki-pluginedit.js
>>> ===================================================================
>>> --- trunk/lib/jquery_tiki/tiki-pluginedit.js 2017-03-13 12:09:36 UTC (rev 61663)
>>> +++ trunk/lib/jquery_tiki/tiki-pluginedit.js 2017-03-13 14:58:28 UTC (rev 61664)
>>> @@ -82,137 +82,30 @@
>>> replaceText = false;
>>> }
>>> }
>>> - var form = build_plugin_form(type, index, pageName, pluginArgs, bodyContent,
>> selectedMod);
>>>
>>> - //with PluginModule, if the user selects another module while the edit form is open
>>> - //replace the form with a new one with fields to match the parameters for the module
>> selected
>>> - $(form).find('tr select[name="params[module]"]').change(function () {
>>> - var npluginArgs =
>> $.parseJSON($(form).find('input[name="args"][type="hidden"]').val());
>>> - //this is the newly selected module
>>> - var selectedMod = $(form).find('tr select[name="params[module]"]').val();
>>> - $('div.plugin input[name="type"][value="' + type +
>> '"]').parent().parent().remove();
>>> - popupPluginForm(area_id, type, index, pageName, npluginArgs, bodyContent,
>> edit_icon, selectedMod);
>>> - });
>>> - var $form = $(form).find('tr input[type=submit]').remove();
>>> -
>>> - container.append(form);
>>> -
>>> -
>>> - var pfc = container.find('table tr').length; // number of rows (plugin form
>> contents)
>>> - var t = container.find('textarea:visible').length;
>>> - if (t) {
>>> - pfc += t * 3;
>>> - }
>>> - if (pfc > 9) {
>>> - pfc = 9;
>>> - }
>>> - if (pfc < 2) {
>>> - pfc = 2;
>>> - }
>>> - pfc = pfc / 10; // factor to scale dialog height
>>> -
>>> - var $closeBtn = $('<button>')
>>> - .text(tr("Close"))
>>> - .addClass('btn btn-default')
>>> - .click(function () {
>>> - $(this).parents(".modal").modal("hide");
>>> - });
>>> -
>>> - var $submitBtn = $('<button>')
>>> - .text(replaceText ? tr("Replace") : edit_icon ? tr("Submit") : tr("Insert"))
>>> - .addClass('btn btn-primary')
>>> - .click(function () {
>>> -
>>> - $(this).off("click").css("opacity", 0.3);
>>> -
>>> - var meta = tiki_plugins[type];
>>> - var params = [];
>>> - var edit = edit_icon;
>>> - // whether empty required params exist or not
>>> - var emptyRequiredParam = false;
>>> -
>>> - for (var i = 0; i < form.elements.length; i++) {
>>> - var element = form.elements[i].name;
>>> -
>>> - var matches = element.match(/params\[(.*)\]/);
>>> -
>>> - if (matches === null) {
>>> - // it's not a parameter, skip
>>> - continue;
>>> - }
>>> - var param = matches[1];
>>> -
>>> - var val = form.elements[i].value;
>>> -
>>> - // check if fields that are required and visible are not empty
>>> - if (meta.params[param]) {
>>> - if (meta.params[param].required) {
>>> - if (val === '' && $(form.elements[i]).is(':visible'))
>> {
>>> - $(form.elements[i]).css('border-color',
>> 'red');
>>> - if
>> ($(form.elements[i]).next('.required_param').length === 0) {
>>> - $(form.elements[i]).after('<div
>> class="required_param" style="font-size: x-small; color: red;">(required)</div>');
>>> - }
>>> - emptyRequiredParam = true;
>>> - }
>>> - else {
>>> - // remove required feedback if present
>>> - $(form.elements[i]).css('border-color',
>> '');
>>> -
>> $(form.elements[i]).next('.required_param').remove();
>>> - }
>>> - }
>>> - }
>>> -
>>> - if (val !== '') {
>>> - if (!edit) {
>>> - val = val.replace(/"/g, '\\"'); // escape double
>> quotes
>>> - }
>>> - params.push(param + '="' + val + '"');
>>> - }
>>> - }
>>> -
>>> - if (emptyRequiredParam) {
>>> - return false;
>>> - }
>>> -
>>> - var blob, pluginContentTextarea = $("[name=content]", form),
>>> - pluginContentTextareaEditor =
>> syntaxHighlighter.get(pluginContentTextarea);
>>> - var cont = (pluginContentTextareaEditor ?
>> pluginContentTextareaEditor.getValue() : pluginContentTextarea.val());
>>> -
>>> - if (meta.body) {
>>> - blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' +
>> cont + '{' + type.toUpperCase() + '}';
>>> - } else {
>>> - blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}';
>>> - }
>>> -
>>> - if (edit) {
>>> - container.children('form').submit();
>>> - // quick and dirty reload
>>> - window.location = window.location.href;
>>> - } else {
>>> - insertAt(area_id, blob, false, false, replaceText);
>>> - }
>>> - $modal.modal("hide");
>>> -
>>> - return false;
>>> - });
>>> -
>>> - var heading = container.find('h3').hide();
>>> -
>>> var $modal = $('.modal.fade:not(.in)').first();
>>>
>>> - $modal.find(".modal-dialog").empty()
>>> - .append($("<div>").addClass("modal-content")
>>> - .append($("<div>").addClass("modal-
>> header").append($("<h4>").addClass("modal-title").text(heading.text())))
>>> - .append($("<div>").addClass("modal-body").append(container))
>>> - .append($("<div>").addClass("modal-footer").append($closeBtn,
>> $submitBtn))
>>> - );
>>> + var url = $.service("plugin", "edit", {
>>> + area_id: area_id,
>>> + type: type,
>>> + index: index,
>>> + page: pageName,
>>> + pluginArgs: pluginArgs,
>>> + bodyContent: bodyContent,
>>> + edit_icon: edit_icon,
>>> + selectedMod: selectedMod ? selectedMod : "",
>>> + modal: 1
>>> + });
>>>
>>> // Make the form appear
>>> - $modal.modal({
>>> - show: false // if it;'s the first time the show.bs.modal
>> doesn't trigger sometimes
>>> - })
>>> - .one('show.bs.modal', function () { // Bind open event
>>> + $modal
>>> + .modal({
>>> + remote: url,
>>> + show: false // if it's the first time the show.bs.modal
>> doesn't trigger sometimes
>>> + })
>>> + .one('loaded.bs.modal', function () { // Bind remote loaded
>> event
>>> handlePluginFieldsHierarchy(type);
>>> + handleFormSubmit(this, type, edit_icon, area_id, replaceText);
>>> })
>>> .modal("show");
>>>
>>> @@ -231,7 +124,7 @@
>>> arguments: arguments,
>>> modal: $modal
>>> });
>>> - }
>>> + };
>>>
>>> /*
>>> * Hides all children fields in a wiki-plugin form and @@ -240,14
>>> +133,15 @@
>>> */
>>> function handlePluginFieldsHierarchy(type) {
>>> var pluginParams = tiki_plugins[type]['params'];
>>> + var $container = $('#plugin_params');
>>>
>>> var parents = {};
>>>
>>> $.each(pluginParams, function (paramName, paramValues) {
>>> if (paramValues.parent) {
>>> - var $parent = $('[name$="params[' + paramValues.parent.name + ']"]',
>> '.wikiplugin_edit');
>>> + var $parent = $('[name$="params[' + paramValues.parent.name +
>>> +']"]', $container);
>>>
>>> - var $row = $('.wikiplugin_edit').find('#param_' + paramName);
>>> + var $row = $container.find('#param_' + paramName);
>>> $row.addClass('parent_' + paramValues.parent.name + '_' +
>>> paramValues.parent.value);
>>>
>>> if ($parent.val() !== paramValues.parent.value) { @@ -271,14
>>> +165,69 @@
>>> $.each(parents, function (parentName, parent) {
>>> parent.parentElement.change(function () {
>>> $.each(parent.children, function () {
>>> - $('.wikiplugin_edit #param_' + this).hide();
>>> + $container.find('#param_' + this).hide();
>>> });
>>> - $('.wikiplugin_edit .parent_' + parentName + '_' + this.value).show();
>>> + $container.find('.parent_' + parentName + '_' +
>>> +this.value).show();
>>> })
>>> .change().trigger("chosen:updated");
>>> });
>>> }
>>>
>>> + /**
>>> + * set up insert/replace button and submit handler in "textarea" edit mode
>>> + *
>>> + * @param container
>>> + * @param type
>>> + * @param edit_icon
>>> + * @param area_id
>>> + */
>>> + function handleFormSubmit(container, type, edit_icon, area_id,
>>> +replaceText) {
>>> +
>>> + var meta = tiki_plugins[type], params = [], edit = !!edit_icon,
>>> +emptyRequiredParam = false;
>>> +
>>> + var $form = $("form", container);
>>> +
>>> + $form.submit(function () {
>>> +
>>> + if (!process_submit(this)) {
>>> + return false;
>>> + }
>>> +
>>> + $(".form-control", $form).each(function () {
>>> +
>>> + var matches = $(this).attr("name").match(/params\[(.*)\]/),
>>> + val = $(this).val();
>>> +
>>> + if (!matches) {
>>> + // it's not a parameter, skip
>>> + return;
>>> + }
>>> +
>>> + if (val&& !edit) {
>>> + val = val.replace(/"/g, '\\"'); // escape double quotes
>>> + params.push(matches[1] + '="' + val + '"');
>>> + }
>>> + });
>>> +
>>> + var blob, pluginContentTextarea = $("[name=content]", $form),
>>> + pluginContentTextareaEditor =
>> syntaxHighlighter.get(pluginContentTextarea),
>>> + cont = (pluginContentTextareaEditor ?
>>> +pluginContentTextareaEditor.getValue() :
>>> +pluginContentTextarea.val());
>>> +
>>> + if (!edit) {
>>> + if (meta.body) {
>>> + blob = '{' + type.toUpperCase() + '(' + params.join(' ') + ')}' +
>> cont + '{' + type.toUpperCase() + '}';
>>> + } else {
>>> + blob = '{' + type.toLowerCase() + ' ' + params.join(' ') + '}';
>>> + }
>>> +
>>> + insertAt(area_id, blob, false, false, replaceText);
>>> + $(container).modal("hide");
>>> +
>>> + return false;
>>> + }
>>> + });
>>> + }
>>> +
>>> function dialogSelectElement(area_id, elementStart, elementEnd) {
>>> if (typeof CKEDITOR !== 'undefined' && typeof CKEDITOR.instances[area_id] !==
>> 'undefined') {
>>> return;
>>> @@ -317,325 +266,4 @@
>>>
>>> }
>>>
>>> -
>>> - function build_plugin_form(type, index, pageName, pluginArgs, bodyContent, selectedMod) {
>>> - var form = document.createElement('form');
>>> - form.method = 'post';
>>> - form.action = 'tiki-wikiplugin_edit.php';
>>> - form.className = 'wikiplugin_edit';
>>> -
>>> - var hiddenPage = document.createElement('input');
>>> - hiddenPage.type = 'hidden';
>>> - hiddenPage.name = 'page';
>>> - hiddenPage.value = pageName;
>>> - form.appendChild(hiddenPage);
>>> -
>>> - var hiddenType = document.createElement('input');
>>> - hiddenType.type = 'hidden';
>>> - hiddenType.name = 'type';
>>> - hiddenType.value = type;
>>> - form.appendChild(hiddenType);
>>> -
>>> - var hiddenIndex = document.createElement('input');
>>> - hiddenIndex.type = 'hidden';
>>> - hiddenIndex.name = 'index';
>>> - hiddenIndex.value = index;
>>> - form.appendChild(hiddenIndex);
>>> -
>>> - //
>>> - var savedArgs = document.createElement('input');
>>> - savedArgs.type = 'hidden';
>>> - savedArgs.name = 'args';
>>> - savedArgs.value = $.toJSON(pluginArgs);
>>> - form.appendChild(savedArgs);
>>> -
>>> - //Convert to JSON and then back to an object to break
>>> - //link between meta local variable and tiki_plugins[type] global variable.
>>> - //Otherwise each change to meta.params using the extend below was being
>> appended to the global
>>> - //Probably a much easier way to do this
>>> - var infostring = $.toJSON(tiki_plugins[type]);
>>> - var meta = $.parseJSON(infostring);
>>> -
>>> - //For PluginModule, add selected module parameters to the plugin edit form
>>> - if (type == 'module') {
>>> - //isolate the module parameter object so it will be shown first in the form
>>> - var onlymod = {"params": {"module": meta.params.module}};
>>> - //user has not changed the module selection since opening the form
>>> - if (typeof selectedMod == 'undefined') {
>>> - //pick up the parameters of the saved module parameter
>>> - if (typeof pluginArgs.module != 'undefined') {
>>> - //this orders the module parameter first, module related
>> parameters second, other PluginModule parameters besides module last
>>> - meta.params = $.extend(onlymod.params,
>> tiki_module_params[pluginArgs.module].params, meta.params);
>>> - //Use the module description
>>> - meta.params.module.description =
>> tiki_module_params[pluginArgs.module].description;
>>> - //otherwise pick up the parameters of the first module option
>> since that will be selected automatically
>>> - } else {
>>> - meta.params = $.extend(onlymod.params,
>> tiki_module_params[meta.params.module.options[0].value].params, meta.params);
>>> - meta.params.module.description =
>> tiki_module_params[meta.params.module.options[0].value].description;
>>> - }
>>> - //user has selected another module while the form was open - pick up
>> parameters for the selected module
>>> - } else if (tiki_module_params[selectedMod] != null) {
>>> - meta.params = $.extend(onlymod.params,
>> tiki_module_params[selectedMod].params, meta.params);
>>> - meta.params.module.description =
>> tiki_module_params[selectedMod].description;
>>> - }
>>> - }
>>> -
>>> - var header = document.createElement('h3');
>>> - header.innerHTML = meta.name;
>>> - form.appendChild(header);
>>> -
>>> - var desc = document.createElement('div');
>>> - desc.innerHTML = meta.description;
>>> - if (meta.documentation && jqueryTiki.helpurl) {
>>> - desc.innerHTML += ' <a href="' + jqueryTiki.helpurl + meta.documentation + '"
>> target="tikihelp" class="tikihelp" tabIndex="-1" title="' + tr('Help') + '">' +
>>> - '<span class="icon icon-help fa fa-question-circle fa-fw"></span>' +
>>> - '</a>';
>>> -
>>> - }
>>> - form.appendChild(desc);
>>> -
>>> - var table = document.createElement('table'), param;
>>> - table.className = 'table';
>>> - table.id = 'plugin_params';
>>> - form.appendChild(table);
>>> -
>>> - for (param in meta.params) {
>>> - if (meta.params[param].advanced) {
>>> - var br = document.createElement('br');
>>> - form.appendChild(br);
>>> -
>>> - var span_advanced_button = document.createElement('span');
>>> - span_advanced_button.className = 'button';
>>> - form.appendChild(span_advanced_button);
>>> -
>>> - var advanced_button = document.createElement('a');
>>> - advanced_button.innerHTML = tr('Advanced options');
>>> - advanced_button.onclick = function () {
>>> - flip('plugin_params_advanced');
>>> - };
>>> - span_advanced_button.appendChild(advanced_button);
>>> -
>>> - var table_advanced = document.createElement('table');
>>> - table_advanced.className = 'normal';
>>> - table_advanced.style.display = 'none';
>>> - table_advanced.id = 'plugin_params_advanced';
>>> - form.appendChild(table_advanced);
>>> -
>>> - break;
>>> - }
>>> - }
>>> -
>>> - var potentiallyExtraPluginArgs = pluginArgs, extraArg;
>>> -
>>> - var rowNumber = 0;
>>> - var rowNumberAdvanced = 0;
>>> - for (param in meta.params) {
>>> - if (typeof(meta.params[param]) != 'object' || meta.params[param].name ==
>> 'array') {
>>> - continue;
>>> - }
>>> -
>>> - var row;
>>> - if (meta.params[param].advanced && !meta.params[param].required &&
>> typeof pluginArgs[param] === "undefined") {
>>> - row = table_advanced.insertRow(rowNumberAdvanced++);
>>> - } else {
>>> - row = table.insertRow(rowNumber++);
>>> - }
>>> - var value = pluginArgs.length < 1 ? '' : pluginArgs[param];// for param like sort
>>> - //for use with PluginModule to identify saved module parameter value
>>> - var nsavedArgs =
>> $.parseJSON($(form).find('input[name="args"][type="hidden"]').val());
>>> - //last two parameters (selectedMod and savedArgs are only needed for
>> PluginModule
>>> - build_plugin_form_row(row, param, meta.params[param].name,
>> meta.params[param].required, value, meta.params[param].description, meta.params[param],
>> selectedMod, nsavedArgs);
>>> -
>>> - delete potentiallyExtraPluginArgs[param];
>>> - }
>>> -
>>> - for (extraArg in potentiallyExtraPluginArgs) {
>>> - if (extraArg === '') {
>>> - // TODO HACK: See bug 2499 http://dev.tiki.org/tiki-
>> view_tracker_item.php?itemId=2499
>>> - continue;
>>> - }
>>> -
>>> - row = table.insertRow(rowNumber++);
>>> - build_plugin_form_row(row, extraArg, extraArg, 'extra', pluginArgs[extraArg],
>> extraArg);
>>> - }
>>> -
>>> - var bodyRow = table.insertRow(rowNumber++);
>>> - var bodyCell = bodyRow.insertCell(0);
>>> - var bodyField = document.createElement('textarea');
>>> - bodyField.rows = '12';
>>> - bodyField.className = 'form-control';
>>> - var bodyDesc = document.createElement('div');
>>> -
>>> - if (meta.body) {
>>> - bodyDesc.innerHTML = meta.body;
>>> - } else {
>>> - bodyRow.style.display = 'none';
>>> - }
>>> - bodyField.name = 'content';
>>> - bodyField.value = bodyContent;
>>> -
>>> - bodyRow.className = 'formcolor';
>>> -
>>> - bodyCell.appendChild(bodyDesc);
>>> - bodyCell.appendChild(bodyField);
>>> - bodyCell.colSpan = '2';
>>> -
>>> - var submitRow = table.insertRow(rowNumber++);
>>> - var submitCell = submitRow.insertCell(0);
>>> - var submit = document.createElement('input');
>>> -
>>> - submit.type = 'submit';
>>> - submitCell.colSpan = 2;
>>> - submitCell.appendChild(submit);
>>> - submitCell.className = 'submit';
>>> -
>>> - return form;
>>> - }
>>> -
>>> -//last two parameters (selectedMod and savedArgs are only needed for PluginModule
>>> - function build_plugin_form_row(row, name, label_name, requiredOrSpecial, value,
>> description, paramDef, selectedMod, savedArgs) {
>>> -
>>> - var label = row.insertCell(0);
>>> - var field = row.insertCell(1);
>>> - row.className = 'form-group';
>>> - row.id = 'param_' + name;
>>> -
>>> - label.innerHTML = label_name;
>>> - label.className = 'col-sm-3';
>>> - field.className = 'col-sm-9';
>>> - switch (requiredOrSpecial) {
>>> - case (true):  // required flag
>>> - label.style.fontWeight = 'bold';
>>> - break;
>>> - case ('extra') :
>>> - label.style.fontStyle = 'italic';
>>> - }
>>> -
>>> - var input, icon;
>>> - if (paramDef && paramDef.options) {
>>> - input = document.createElement('select');
>>> - input.name = 'params[' + name + ']';
>>> - input.className = 'form-control';
>>> - for (var o = 0; o < paramDef.options.length; o++) {
>>> - var opt = document.createElement('option');
>>> - opt.value = paramDef.options[o].value;
>>> - var opt_text = document.createTextNode(paramDef.options[o].text);
>>> - opt.appendChild(opt_text);
>>> - //either not PluginModule or user has not changed module selection,
>> so use saved value
>>> - if (typeof selectedMod == 'undefined') {
>>> - if (value && opt.value == value) {
>>> - opt.selected = true;
>>> - }
>>> - } else {
>>> - //user changed module selection in PluginModule
>>> - if (selectedMod == opt.value) {
>>> - opt.selected = true;
>>> - } else if (savedArgs.module == opt.value) {
>>> - //use later to display saved module parameter value
>>> - var savedtext = opt.innerHTML;
>>> - opt.style.fontWeight = 'bold';
>>> - opt.innerHTML = opt.innerHTML + '  -- ' + tr('saved
>> value');
>>> - }
>>> - }
>>> - input.appendChild(opt);
>>> - }
>>> - } else {
>>> - input = document.createElement('input');
>>> - input.className = 'form-control';
>>> - input.type = 'text';
>>> - input.name = 'params[' + name + ']';
>>> - if (value) {
>>> - input.value = value.replace(/\\"/g, '"'); // unescape quotes
>>> - }
>>> - }
>>> -
>>> - field.appendChild(input);
>>> - if (paramDef && paramDef.type == 'image') {
>>> - icon = document.createElement('img');
>>> - icon.src = 'img/icons/image.png';
>>> - input.id = paramDef.area ? paramDef.area : 'fgal_picker';
>>> - icon.onclick = function () {
>>> - openFgalsWindowArea(paramDef.area ? paramDef.area :
>> 'fgal_picker');
>>> - };
>>> - field.appendChild(icon);
>>> - } else if (paramDef && paramDef.type == 'fileId') {
>>> - var help = document.createElement('span');
>>> - input.id = paramDef.area ? paramDef.area : 'fgal_picker';
>>> - help.onclick = function () {
>>> - openFgalsWindowArea(paramDef.area ? paramDef.area :
>> 'fgal_picker');
>>> - };
>>> - help.innerHTML = " <a href='#'>" + tr('Pick a file.') + "</a>";
>>> - field.appendChild(help);
>>> - } else if (paramDef && paramDef.type == 'kaltura') {
>>> - input.id = paramDef.area;
>>> - var img = $("<img />")
>>> - .attr("src", paramDef.icon)
>>> - .addClass("icon")
>>> - .css("cursor", "pointer")
>>> - .attr("title", tr("Upload or record media"))
>>> - ;
>>> - $(field).append(
>>> - $('<a/>')
>>> - .attr('href', $.service('kaltura', 'upload'))
>>> - .append(img)
>>> - .click(function () {
>>> - $(this).serviceDialog({
>>> - title: tr("Upload or record media"),
>>> - width: 710,
>>> - height: 450,
>>> - hideButtons: true,
>>> - success: function (data) {
>>> - if (data.entries) {
>>> - input.value = data.entries[0];
>>> - }
>>> - }
>>> - });
>>> - return false;
>>> - })
>>> - );
>>> - }
>>> -
>>> - if (description) {
>>> - var desc = document.createElement('div');
>>> - desc.style.fontSize = 'x-small';
>>> - desc.innerHTML = description;
>>> - field.appendChild(desc);
>>> - }
>>> - if (paramDef && paramDef.accepted) {
>>> - $(field).append(
>>> - $("<div>")
>>> - .css("fontSize", "x-small")
>>> - .html("<strong>" + tr("Accepted:") + "</strong><br>" +
>> paramDef.accepted)[0]
>>> - );
>>> - }
>>> - //in PluginModule, show saved nodule parameter value if user has changed selection
>>> - //since the form changes to match the newly selected module, it's useful to show the
>>> - //saved module parameter so the user can go back to it
>>> - if (typeof savedtext != 'undefined') {
>>> - var saved = document.createElement('div');
>>> - saved.style.fontSize = 'x-small';
>>> - saved.style.fontStyle = 'italic';
>>> - saved.style.fontWeight = 'bold';
>>> - saved.innerHTML = tr('Saved value:') + ' ' + savedtext;
>>> - field.appendChild(saved);
>>> - }
>>> -
>>> - if (paramDef && paramDef.filter) {
>>> - if (paramDef.filter == "pagename") {
>>> - $(input).tiki("autocomplete", "pagename");
>>> - } else if (paramDef.filter == "groupname") {
>>> - $(input).tiki("autocomplete", "groupname", {multiple: true,
>> multipleSeparator: "|"});
>>> - } else if (paramDef.filter == "username") {
>>> - $(input).tiki("autocomplete", "username", {multiple: true,
>> multipleSeparator: "|"});
>>> - } else if (paramDef.filter == "date") {
>>> - $(input).tiki("datepicker");
>>> - }
>>> - }
>>> -
>>> - }
>>> -
>>> - function openFgalsWindowArea(area) {
>>> - openFgalsWindow('tiki-list_file_gallery.php?filegals_manager=' + area + '&galleryId=' +
>> jqueryTiki.home_file_gallery, true); // reload
>>> - }
>>> -
>>> })(jQuery);
>>>
>>> Copied: trunk/templates/plugin/edit.tpl (from rev 61597,
>>> trunk/templates/plugin/list.tpl)
>> ===================================================================
>>> --- trunk/templates/plugin/edit.tpl                        (rev 0)
>>> +++ trunk/templates/plugin/edit.tpl 2017-03-13 14:58:28 UTC (rev 61664)
>>> @@ -0,0 +1,116 @@
>>> +{extends 'layout_view.tpl'}
>>> +
>>> +{block name="title"}
>>> + <h3>{$title}</h3>
>>> +{/block}
>>> +
>>> +{block name="content"}
>>> + {function plugin_edit_row}{* needs to be in the same block it seems? *}
>>> + {if
>> $param.area}{$inputId=$param.area|escape}{else}{$inputId="param_{$name|escape}_input"}{/if}
>>> + <div  class="col-sm-3">
>>> + <label for="{$inputId}">{$param.name|escape}</label>
>>> + {if not empty($param.type)}
>>> + {$onclick = "openFgalsWindow('{$prefs.home_file_gallery|sefurl:'file
>> gallery':true}filegals_manager={$param.area|escape}&id=1', true);return false;"}
>>> + {if $param.type eq 'image'}
>>> + <br>{icon name='image' title='{tr}Select image{/tr}'
>> onclick=$onclick class='btn btn-xs btn-default'}
>>> + {elseif $param.type eq 'fileId'}
>>> + <br>{icon name='file' title='{tr}Pick a file{/tr}' onclick=$onclick
>> class='btn btn-xs btn-default'}
>>> + {elseif $param.type eq 'kaltura'}
>>> + {jq}
>>> +$("#picker_{{$name|escape}}").parent().click(function () {
>>> + $(this).serviceDialog({
>>> + title: tr("Upload or record media"),
>>> + width: 710,
>>> + height: 450,
>>> + hideButtons: true,
>>> + success: function (data) {
>>> + if (data.entries) {
>>> + input.value = data.entries[0];
>>> + }
>>> + }
>>> + });
>>> + return false;
>>> +});
>>> + {/jq}
>>> + <br>{icon name='video' title='{tr}Upload or record media{/tr}'
>> href={service controller='kaltura' action='upload'} id='picker_'|cat:$name|escape class='btn btn-xs
>> btn-default'}
>>> + {/if}
>>> + {/if}
>>> + </div>
>>> + <div class="col-sm-9">
>>> + {if (not empty($param.parent.name))}
>>> + {$groupClass = " group-`$param.parent.name`"}
>>> + {else}
>>> + {$groupClass = ''}
>>> + {/if}
>>> + {if empty($param.options)}
>>> + <input value="{if isset($pluginArgs[$name])}{$pluginArgs[$name]}{/if}"
>> class="form-control{$groupClass}" id="{$inputId}" type="text" name="params[{$name|escape}]">
>>> + {if not empty($param.filter)}
>>> + {if $param.filter eq "pagename"}
>>> + {jq}$({{$inputId}}).tiki("autocomplete",
>> "pagename");{/jq}
>>> + {elseif $param.filter eq "groupname"}
>>> + {jq}$({{$inputId}}).tiki("autocomplete", "groupname",
>> {multiple: true, multipleSeparator: "|"});{/jq}
>>> + {elseif $param.filter eq "username"}
>>> + {jq}$({{$inputId}}).tiki("autocomplete", "username",
>> {multiple: true, multipleSeparator: "|"});{/jq}
>>> + {elseif $param.filter eq "date"}
>>> + {jq}$({{$inputId}}).tiki("datepicker");{/jq}
>>> + {/if}
>>> + {/if}
>>> +
>>> + {else}
>>> + <select class="form-control{$groupClass}" type="text"
>> name="params[{$name|escape}]" id="{$inputId}">
>>> + {foreach $param.options as $option}
>>> + <option value="{$option.value|escape}" {if
>> isset($pluginArgs[$name]) and $pluginArgs[$name] eq $option.value} selected="selected"{/if}>
>>> + {$option.text|escape}
>>> + </option>
>>> + {/foreach}
>>> + </select>
>>> + {/if}
>>> + <div class="description">{$param.description}</div>
>>> + </div>
>>> + {/function}
>>> + <div class="form-horizontal" id="plugin_params">
>>> + <form action="{service controller='plugin' action='edit'}" method="post">
>>> + {foreach $info.params as $name => $param}
>>> + <div class="form-group{if $param.advanced} advanced{/if}"
>> id="param_{$name|escape}">
>>> + {plugin_edit_row param=$param name=$name info=$info
>> pluginArgs=$pluginArgs}
>>> + </div>
>>> + {/foreach}
>>> + {if not empty($info.advancedParams)}
>>> + {button _text='Advanced' _onclick="$('.form-
>> group.advanced.default').toggle('fast'); return false;" _class='btn btn-xs margin-bottom-md'}
>>> + {foreach $info.advancedParams as $name => $param}
>>> + <div class="form-group advanced default" style="display:
>> none;">
>>> + {plugin_edit_row param=$param name=$name
>> info=$info pluginArgs=$pluginArgs}
>>> + </div>
>>> + {/foreach}
>>> + {/if}
>>> +
>>> + <div class="form-group"{if empty($info.body)} style="display:none"{/if}>
>>> + <label for="content" class="col-sm-3">{tr}Body{/tr}</label>
>>> + <div class="col-sm-9">
>>> + <textarea name="content" id="content" class="form-
>> control">{$bodyContent|escape}</textarea>
>>> + <div class="description">{$info.body}</div>
>>> + </div>
>>> + </div>
>>> +
>>> + <div class="submit">
>>> + <input type="hidden" name="page" value="{$pageName}">
>>> + <input type="hidden" name="type" value="{$type}">
>>> + <input type="hidden" name="index" value="{$index}">
>>> + <input type="hidden" name="args" value="{$pluginArgsJSON}">
>>> + <input type="submit" class="btn btn-primary" value="{tr}Save{/tr}">
>>> + </div>
>>> +
>>> + {if $type eq 'module'}
>>> + {jq}$("#param_module_input").change(function () {
>>> + var selectMod = $(this).val();
>>> + $.closeModal();
>>> + $(document).one("hidden.bs.modal", function () {
>>> + popupPluginForm("{{$area_id}}","{{$type}}",
>> {{$index}}, "{{$pageName}}", {{$pluginArgsJSON}}, "{{$bodyContent}}", "{{$edit_icon}}", selectMod);
>>> + });
>>> + });{/jq}
>>> + {/if}
>>> +
>>> + </form>
>>> + </div>
>>> +{/block}
>>> +
>>>
>>> Modified: trunk/tiki-wikiplugin_edit.php
>>> ===================================================================
>>> --- trunk/tiki-wikiplugin_edit.php 2017-03-13 12:09:36 UTC (rev 61663)
>>> +++ trunk/tiki-wikiplugin_edit.php 2017-03-13 14:58:28 UTC (rev 61664)
>>> @@ -10,62 +10,9 @@
>>>
>>> require 'tiki-setup.php';
>>>
>>> -if ( ! isset( $_POST['page'], $_POST['content'], $_POST['index'], $_POST['type'],
>> $_SERVER['HTTP_REFERER'] ) )
>>> - die( 'Missing parameters' );
>>> +trigger_error(tr('Note, deprecated file tiki-wikiplugin_edit.php,
>>> +code moved to service plugin->replace'));
>>>
>>> -$page = $_POST['page'];
>>> +TikiLib::lib('service')->render('plugin', 'replace', $jitPost);
>>>
>>> -$plugin = strtolower(basename($_POST['type']));
>>> -$type = TikiLib::strtoupper($plugin);
>>> -
>>> -if (empty($parserlib)) {
>>> - $parserlib = TikiLib::lib('parser');
>>> -}
>>> -
>>> -if ( ! $meta = $parserlib->plugin_info($plugin) )
>>> - exit;
>>> -
>>> -if ( ! isset( $_POST['message'] ) )
>>> - $_POST['message'] = (isset($meta['name']) ? tra($meta['name']) : $plugin) . ' ' . tra('Plugin
>> modified by editor.');
>>> -
>>> -$info = $tikilib->get_page_info($page);
>>> -$tikilib->get_perm_object($page, 'wiki page', $info, true); -if
>>> ($tiki_p_edit != 'y') {
>>> - header("Location: {$_SERVER['HTTP_REFERER']}");
>>> - exit;
>>> -}
>>> -$content = $_POST['content'];
>>> -$current = $info['data'];
>>> -
>>> -$matches = WikiParser_PluginMatcher::match($current);
>>> -$count = 0;
>>> -foreach ( $matches as $match ) {
>>> - if ( $match->getName() !== $plugin ) {
>>> - continue;
>>> - }
>>> -
>>> - ++$count;
>>> -
>>> - if ( $_POST['index'] == $count ) {
>>> - //by using content of "~same~", it will not replace the body that is there
>>> - $content = ($content == "~same~" ? $match->getBody() : $content);
>>> - $params = $match->getArguments();
>>> -
>>> - // If parameters are provided, rebuild the parameter line
>>> - if ( isset( $_POST['params'] ) && is_array($_POST['params']) ) {
>>> - // $values was relaxed to accept any argument rather than those defined up
>> front
>>> - // in the plugin's parameter list. This facilitates the use of modules as plugins.
>>> - $params = $_POST['params'];
>>> - }
>>> -
>>> - $match->replaceWithPlugin($plugin, $params, $content);
>>> -
>>> - $parsed = $matches->getText();
>>> -
>>> - $tikilib->update_page($page, $parsed, $_POST['message'], $user, $tikilib-
>>> get_ip_address());
>>> - break;
>>> - }
>>> -}
>>> -
>>> header("Location: {$_SERVER['HTTP_REFERER']}"); exit;
>>>
>>> This was sent by the SourceForge.net collaborative development platform, the world's largest Open
>> Source development site.
>>>
>>>
>>> ----------------------------------------------------------------------
>>> -------- Check out the vibrant tech community on one of the world's
>>> most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
>>> _______________________________________________
>>> Tikiwiki-cvs mailing list
>>> [hidden email]
>>> https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
>>>
>>
>>
>> ------------------------------------------------------------------------------
>> Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org!
>> http://sdm.link/slashdot _______________________________________________
>> TikiWiki-devel mailing list
>> [hidden email]
>> https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> TikiWiki-devel mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel
>


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
TikiWiki-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-devel
Loading...