diff --git a/admin-dev/themes/new-theme/js/pages/order-preferences/index.js b/admin-dev/themes/new-theme/js/pages/order-preferences/index.js new file mode 100644 index 0000000000000..9eef6a9e8fe35 --- /dev/null +++ b/admin-dev/themes/new-theme/js/pages/order-preferences/index.js @@ -0,0 +1,32 @@ +/** + * 2007-2018 PrestaShop + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to http://www.prestashop.com for more information. + * + * @author PrestaShop SA + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +import TermsAndConditionsOptionHandler from './terms-and-conditions-option-handler'; + +const $ = window.$; + +$(() => { + new TermsAndConditionsOptionHandler(); +}); diff --git a/admin-dev/themes/new-theme/js/pages/order-preferences/terms-and-conditions-option-handler.js b/admin-dev/themes/new-theme/js/pages/order-preferences/terms-and-conditions-option-handler.js new file mode 100644 index 0000000000000..c9bd62e0b92cf --- /dev/null +++ b/admin-dev/themes/new-theme/js/pages/order-preferences/terms-and-conditions-option-handler.js @@ -0,0 +1,53 @@ +/** + * 2007-2018 PrestaShop + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to http://www.prestashop.com for more information. + * + * @author PrestaShop SA + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +const $ = window.$; + +class TermsAndConditionsOptionHandler { + constructor() { + this.handle(); + + $('input[name="form[general][enable_tos]"]').on('change', () => this.handle()); + } + + handle() { + const tosEnabledVal = $('input[name="form[general][enable_tos]"]:checked').val(); + const isTosEnabled = parseInt(tosEnabledVal); + + this.handleTermsAndConditionsCmsSelect(isTosEnabled); + } + + /** + * If terms and conditions option is disabled, then terms and conditions + * cms select must be disabled. + * + * @param {int} isTosEnabled + */ + handleTermsAndConditionsCmsSelect(isTosEnabled) { + $('#form_general_tos_cms_id').prop('disabled', !isTosEnabled); + } +} + +export default TermsAndConditionsOptionHandler; diff --git a/admin-dev/themes/new-theme/public/order_preferences.bundle.js b/admin-dev/themes/new-theme/public/order_preferences.bundle.js new file mode 100644 index 0000000000000..e0be53fe7e9c5 --- /dev/null +++ b/admin-dev/themes/new-theme/public/order_preferences.bundle.js @@ -0,0 +1,847 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ function hotDisposeChunk(chunkId) { +/******/ delete installedChunks[chunkId]; +/******/ } +/******/ var parentHotUpdateCallback = this["webpackHotUpdate"]; +/******/ this["webpackHotUpdate"] = +/******/ function webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars +/******/ hotAddUpdateChunk(chunkId, moreModules); +/******/ if(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules); +/******/ } ; +/******/ +/******/ function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars +/******/ var head = document.getElementsByTagName("head")[0]; +/******/ var script = document.createElement("script"); +/******/ script.type = "text/javascript"; +/******/ script.charset = "utf-8"; +/******/ script.src = __webpack_require__.p + "" + chunkId + "." + hotCurrentHash + ".hot-update.js"; +/******/ head.appendChild(script); +/******/ } +/******/ +/******/ function hotDownloadManifest() { // eslint-disable-line no-unused-vars +/******/ return new Promise(function(resolve, reject) { +/******/ if(typeof XMLHttpRequest === "undefined") +/******/ return reject(new Error("No browser support")); +/******/ try { +/******/ var request = new XMLHttpRequest(); +/******/ var requestPath = __webpack_require__.p + "" + hotCurrentHash + ".hot-update.json"; +/******/ request.open("GET", requestPath, true); +/******/ request.timeout = 10000; +/******/ request.send(null); +/******/ } catch(err) { +/******/ return reject(err); +/******/ } +/******/ request.onreadystatechange = function() { +/******/ if(request.readyState !== 4) return; +/******/ if(request.status === 0) { +/******/ // timeout +/******/ reject(new Error("Manifest request to " + requestPath + " timed out.")); +/******/ } else if(request.status === 404) { +/******/ // no update available +/******/ resolve(); +/******/ } else if(request.status !== 200 && request.status !== 304) { +/******/ // other failure +/******/ reject(new Error("Manifest request to " + requestPath + " failed.")); +/******/ } else { +/******/ // success +/******/ try { +/******/ var update = JSON.parse(request.responseText); +/******/ } catch(e) { +/******/ reject(e); +/******/ return; +/******/ } +/******/ resolve(update); +/******/ } +/******/ }; +/******/ }); +/******/ } +/******/ +/******/ +/******/ +/******/ var hotApplyOnUpdate = true; +/******/ var hotCurrentHash = "47925bc2ba2375c84ead"; // eslint-disable-line no-unused-vars +/******/ var hotCurrentModuleData = {}; +/******/ var hotCurrentChildModule; // eslint-disable-line no-unused-vars +/******/ var hotCurrentParents = []; // eslint-disable-line no-unused-vars +/******/ var hotCurrentParentsTemp = []; // eslint-disable-line no-unused-vars +/******/ +/******/ function hotCreateRequire(moduleId) { // eslint-disable-line no-unused-vars +/******/ var me = installedModules[moduleId]; +/******/ if(!me) return __webpack_require__; +/******/ var fn = function(request) { +/******/ if(me.hot.active) { +/******/ if(installedModules[request]) { +/******/ if(installedModules[request].parents.indexOf(moduleId) < 0) +/******/ installedModules[request].parents.push(moduleId); +/******/ } else { +/******/ hotCurrentParents = [moduleId]; +/******/ hotCurrentChildModule = request; +/******/ } +/******/ if(me.children.indexOf(request) < 0) +/******/ me.children.push(request); +/******/ } else { +/******/ console.warn("[HMR] unexpected require(" + request + ") from disposed module " + moduleId); +/******/ hotCurrentParents = []; +/******/ } +/******/ return __webpack_require__(request); +/******/ }; +/******/ var ObjectFactory = function ObjectFactory(name) { +/******/ return { +/******/ configurable: true, +/******/ enumerable: true, +/******/ get: function() { +/******/ return __webpack_require__[name]; +/******/ }, +/******/ set: function(value) { +/******/ __webpack_require__[name] = value; +/******/ } +/******/ }; +/******/ }; +/******/ for(var name in __webpack_require__) { +/******/ if(Object.prototype.hasOwnProperty.call(__webpack_require__, name) && name !== "e") { +/******/ Object.defineProperty(fn, name, ObjectFactory(name)); +/******/ } +/******/ } +/******/ fn.e = function(chunkId) { +/******/ if(hotStatus === "ready") +/******/ hotSetStatus("prepare"); +/******/ hotChunksLoading++; +/******/ return __webpack_require__.e(chunkId).then(finishChunkLoading, function(err) { +/******/ finishChunkLoading(); +/******/ throw err; +/******/ }); +/******/ +/******/ function finishChunkLoading() { +/******/ hotChunksLoading--; +/******/ if(hotStatus === "prepare") { +/******/ if(!hotWaitingFilesMap[chunkId]) { +/******/ hotEnsureUpdateChunk(chunkId); +/******/ } +/******/ if(hotChunksLoading === 0 && hotWaitingFiles === 0) { +/******/ hotUpdateDownloaded(); +/******/ } +/******/ } +/******/ } +/******/ }; +/******/ return fn; +/******/ } +/******/ +/******/ function hotCreateModule(moduleId) { // eslint-disable-line no-unused-vars +/******/ var hot = { +/******/ // private stuff +/******/ _acceptedDependencies: {}, +/******/ _declinedDependencies: {}, +/******/ _selfAccepted: false, +/******/ _selfDeclined: false, +/******/ _disposeHandlers: [], +/******/ _main: hotCurrentChildModule !== moduleId, +/******/ +/******/ // Module API +/******/ active: true, +/******/ accept: function(dep, callback) { +/******/ if(typeof dep === "undefined") +/******/ hot._selfAccepted = true; +/******/ else if(typeof dep === "function") +/******/ hot._selfAccepted = dep; +/******/ else if(typeof dep === "object") +/******/ for(var i = 0; i < dep.length; i++) +/******/ hot._acceptedDependencies[dep[i]] = callback || function() {}; +/******/ else +/******/ hot._acceptedDependencies[dep] = callback || function() {}; +/******/ }, +/******/ decline: function(dep) { +/******/ if(typeof dep === "undefined") +/******/ hot._selfDeclined = true; +/******/ else if(typeof dep === "object") +/******/ for(var i = 0; i < dep.length; i++) +/******/ hot._declinedDependencies[dep[i]] = true; +/******/ else +/******/ hot._declinedDependencies[dep] = true; +/******/ }, +/******/ dispose: function(callback) { +/******/ hot._disposeHandlers.push(callback); +/******/ }, +/******/ addDisposeHandler: function(callback) { +/******/ hot._disposeHandlers.push(callback); +/******/ }, +/******/ removeDisposeHandler: function(callback) { +/******/ var idx = hot._disposeHandlers.indexOf(callback); +/******/ if(idx >= 0) hot._disposeHandlers.splice(idx, 1); +/******/ }, +/******/ +/******/ // Management API +/******/ check: hotCheck, +/******/ apply: hotApply, +/******/ status: function(l) { +/******/ if(!l) return hotStatus; +/******/ hotStatusHandlers.push(l); +/******/ }, +/******/ addStatusHandler: function(l) { +/******/ hotStatusHandlers.push(l); +/******/ }, +/******/ removeStatusHandler: function(l) { +/******/ var idx = hotStatusHandlers.indexOf(l); +/******/ if(idx >= 0) hotStatusHandlers.splice(idx, 1); +/******/ }, +/******/ +/******/ //inherit from previous dispose call +/******/ data: hotCurrentModuleData[moduleId] +/******/ }; +/******/ hotCurrentChildModule = undefined; +/******/ return hot; +/******/ } +/******/ +/******/ var hotStatusHandlers = []; +/******/ var hotStatus = "idle"; +/******/ +/******/ function hotSetStatus(newStatus) { +/******/ hotStatus = newStatus; +/******/ for(var i = 0; i < hotStatusHandlers.length; i++) +/******/ hotStatusHandlers[i].call(null, newStatus); +/******/ } +/******/ +/******/ // while downloading +/******/ var hotWaitingFiles = 0; +/******/ var hotChunksLoading = 0; +/******/ var hotWaitingFilesMap = {}; +/******/ var hotRequestedFilesMap = {}; +/******/ var hotAvailableFilesMap = {}; +/******/ var hotDeferred; +/******/ +/******/ // The update info +/******/ var hotUpdate, hotUpdateNewHash; +/******/ +/******/ function toModuleId(id) { +/******/ var isNumber = (+id) + "" === id; +/******/ return isNumber ? +id : id; +/******/ } +/******/ +/******/ function hotCheck(apply) { +/******/ if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status"); +/******/ hotApplyOnUpdate = apply; +/******/ hotSetStatus("check"); +/******/ return hotDownloadManifest().then(function(update) { +/******/ if(!update) { +/******/ hotSetStatus("idle"); +/******/ return null; +/******/ } +/******/ hotRequestedFilesMap = {}; +/******/ hotWaitingFilesMap = {}; +/******/ hotAvailableFilesMap = update.c; +/******/ hotUpdateNewHash = update.h; +/******/ +/******/ hotSetStatus("prepare"); +/******/ var promise = new Promise(function(resolve, reject) { +/******/ hotDeferred = { +/******/ resolve: resolve, +/******/ reject: reject +/******/ }; +/******/ }); +/******/ hotUpdate = {}; +/******/ var chunkId = 7; +/******/ { // eslint-disable-line no-lone-blocks +/******/ /*globals chunkId */ +/******/ hotEnsureUpdateChunk(chunkId); +/******/ } +/******/ if(hotStatus === "prepare" && hotChunksLoading === 0 && hotWaitingFiles === 0) { +/******/ hotUpdateDownloaded(); +/******/ } +/******/ return promise; +/******/ }); +/******/ } +/******/ +/******/ function hotAddUpdateChunk(chunkId, moreModules) { // eslint-disable-line no-unused-vars +/******/ if(!hotAvailableFilesMap[chunkId] || !hotRequestedFilesMap[chunkId]) +/******/ return; +/******/ hotRequestedFilesMap[chunkId] = false; +/******/ for(var moduleId in moreModules) { +/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { +/******/ hotUpdate[moduleId] = moreModules[moduleId]; +/******/ } +/******/ } +/******/ if(--hotWaitingFiles === 0 && hotChunksLoading === 0) { +/******/ hotUpdateDownloaded(); +/******/ } +/******/ } +/******/ +/******/ function hotEnsureUpdateChunk(chunkId) { +/******/ if(!hotAvailableFilesMap[chunkId]) { +/******/ hotWaitingFilesMap[chunkId] = true; +/******/ } else { +/******/ hotRequestedFilesMap[chunkId] = true; +/******/ hotWaitingFiles++; +/******/ hotDownloadUpdateChunk(chunkId); +/******/ } +/******/ } +/******/ +/******/ function hotUpdateDownloaded() { +/******/ hotSetStatus("ready"); +/******/ var deferred = hotDeferred; +/******/ hotDeferred = null; +/******/ if(!deferred) return; +/******/ if(hotApplyOnUpdate) { +/******/ hotApply(hotApplyOnUpdate).then(function(result) { +/******/ deferred.resolve(result); +/******/ }, function(err) { +/******/ deferred.reject(err); +/******/ }); +/******/ } else { +/******/ var outdatedModules = []; +/******/ for(var id in hotUpdate) { +/******/ if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) { +/******/ outdatedModules.push(toModuleId(id)); +/******/ } +/******/ } +/******/ deferred.resolve(outdatedModules); +/******/ } +/******/ } +/******/ +/******/ function hotApply(options) { +/******/ if(hotStatus !== "ready") throw new Error("apply() is only allowed in ready status"); +/******/ options = options || {}; +/******/ +/******/ var cb; +/******/ var i; +/******/ var j; +/******/ var module; +/******/ var moduleId; +/******/ +/******/ function getAffectedStuff(updateModuleId) { +/******/ var outdatedModules = [updateModuleId]; +/******/ var outdatedDependencies = {}; +/******/ +/******/ var queue = outdatedModules.slice().map(function(id) { +/******/ return { +/******/ chain: [id], +/******/ id: id +/******/ }; +/******/ }); +/******/ while(queue.length > 0) { +/******/ var queueItem = queue.pop(); +/******/ var moduleId = queueItem.id; +/******/ var chain = queueItem.chain; +/******/ module = installedModules[moduleId]; +/******/ if(!module || module.hot._selfAccepted) +/******/ continue; +/******/ if(module.hot._selfDeclined) { +/******/ return { +/******/ type: "self-declined", +/******/ chain: chain, +/******/ moduleId: moduleId +/******/ }; +/******/ } +/******/ if(module.hot._main) { +/******/ return { +/******/ type: "unaccepted", +/******/ chain: chain, +/******/ moduleId: moduleId +/******/ }; +/******/ } +/******/ for(var i = 0; i < module.parents.length; i++) { +/******/ var parentId = module.parents[i]; +/******/ var parent = installedModules[parentId]; +/******/ if(!parent) continue; +/******/ if(parent.hot._declinedDependencies[moduleId]) { +/******/ return { +/******/ type: "declined", +/******/ chain: chain.concat([parentId]), +/******/ moduleId: moduleId, +/******/ parentId: parentId +/******/ }; +/******/ } +/******/ if(outdatedModules.indexOf(parentId) >= 0) continue; +/******/ if(parent.hot._acceptedDependencies[moduleId]) { +/******/ if(!outdatedDependencies[parentId]) +/******/ outdatedDependencies[parentId] = []; +/******/ addAllToSet(outdatedDependencies[parentId], [moduleId]); +/******/ continue; +/******/ } +/******/ delete outdatedDependencies[parentId]; +/******/ outdatedModules.push(parentId); +/******/ queue.push({ +/******/ chain: chain.concat([parentId]), +/******/ id: parentId +/******/ }); +/******/ } +/******/ } +/******/ +/******/ return { +/******/ type: "accepted", +/******/ moduleId: updateModuleId, +/******/ outdatedModules: outdatedModules, +/******/ outdatedDependencies: outdatedDependencies +/******/ }; +/******/ } +/******/ +/******/ function addAllToSet(a, b) { +/******/ for(var i = 0; i < b.length; i++) { +/******/ var item = b[i]; +/******/ if(a.indexOf(item) < 0) +/******/ a.push(item); +/******/ } +/******/ } +/******/ +/******/ // at begin all updates modules are outdated +/******/ // the "outdated" status can propagate to parents if they don't accept the children +/******/ var outdatedDependencies = {}; +/******/ var outdatedModules = []; +/******/ var appliedUpdate = {}; +/******/ +/******/ var warnUnexpectedRequire = function warnUnexpectedRequire() { +/******/ console.warn("[HMR] unexpected require(" + result.moduleId + ") to disposed module"); +/******/ }; +/******/ +/******/ for(var id in hotUpdate) { +/******/ if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) { +/******/ moduleId = toModuleId(id); +/******/ var result; +/******/ if(hotUpdate[id]) { +/******/ result = getAffectedStuff(moduleId); +/******/ } else { +/******/ result = { +/******/ type: "disposed", +/******/ moduleId: id +/******/ }; +/******/ } +/******/ var abortError = false; +/******/ var doApply = false; +/******/ var doDispose = false; +/******/ var chainInfo = ""; +/******/ if(result.chain) { +/******/ chainInfo = "\nUpdate propagation: " + result.chain.join(" -> "); +/******/ } +/******/ switch(result.type) { +/******/ case "self-declined": +/******/ if(options.onDeclined) +/******/ options.onDeclined(result); +/******/ if(!options.ignoreDeclined) +/******/ abortError = new Error("Aborted because of self decline: " + result.moduleId + chainInfo); +/******/ break; +/******/ case "declined": +/******/ if(options.onDeclined) +/******/ options.onDeclined(result); +/******/ if(!options.ignoreDeclined) +/******/ abortError = new Error("Aborted because of declined dependency: " + result.moduleId + " in " + result.parentId + chainInfo); +/******/ break; +/******/ case "unaccepted": +/******/ if(options.onUnaccepted) +/******/ options.onUnaccepted(result); +/******/ if(!options.ignoreUnaccepted) +/******/ abortError = new Error("Aborted because " + moduleId + " is not accepted" + chainInfo); +/******/ break; +/******/ case "accepted": +/******/ if(options.onAccepted) +/******/ options.onAccepted(result); +/******/ doApply = true; +/******/ break; +/******/ case "disposed": +/******/ if(options.onDisposed) +/******/ options.onDisposed(result); +/******/ doDispose = true; +/******/ break; +/******/ default: +/******/ throw new Error("Unexception type " + result.type); +/******/ } +/******/ if(abortError) { +/******/ hotSetStatus("abort"); +/******/ return Promise.reject(abortError); +/******/ } +/******/ if(doApply) { +/******/ appliedUpdate[moduleId] = hotUpdate[moduleId]; +/******/ addAllToSet(outdatedModules, result.outdatedModules); +/******/ for(moduleId in result.outdatedDependencies) { +/******/ if(Object.prototype.hasOwnProperty.call(result.outdatedDependencies, moduleId)) { +/******/ if(!outdatedDependencies[moduleId]) +/******/ outdatedDependencies[moduleId] = []; +/******/ addAllToSet(outdatedDependencies[moduleId], result.outdatedDependencies[moduleId]); +/******/ } +/******/ } +/******/ } +/******/ if(doDispose) { +/******/ addAllToSet(outdatedModules, [result.moduleId]); +/******/ appliedUpdate[moduleId] = warnUnexpectedRequire; +/******/ } +/******/ } +/******/ } +/******/ +/******/ // Store self accepted outdated modules to require them later by the module system +/******/ var outdatedSelfAcceptedModules = []; +/******/ for(i = 0; i < outdatedModules.length; i++) { +/******/ moduleId = outdatedModules[i]; +/******/ if(installedModules[moduleId] && installedModules[moduleId].hot._selfAccepted) +/******/ outdatedSelfAcceptedModules.push({ +/******/ module: moduleId, +/******/ errorHandler: installedModules[moduleId].hot._selfAccepted +/******/ }); +/******/ } +/******/ +/******/ // Now in "dispose" phase +/******/ hotSetStatus("dispose"); +/******/ Object.keys(hotAvailableFilesMap).forEach(function(chunkId) { +/******/ if(hotAvailableFilesMap[chunkId] === false) { +/******/ hotDisposeChunk(chunkId); +/******/ } +/******/ }); +/******/ +/******/ var idx; +/******/ var queue = outdatedModules.slice(); +/******/ while(queue.length > 0) { +/******/ moduleId = queue.pop(); +/******/ module = installedModules[moduleId]; +/******/ if(!module) continue; +/******/ +/******/ var data = {}; +/******/ +/******/ // Call dispose handlers +/******/ var disposeHandlers = module.hot._disposeHandlers; +/******/ for(j = 0; j < disposeHandlers.length; j++) { +/******/ cb = disposeHandlers[j]; +/******/ cb(data); +/******/ } +/******/ hotCurrentModuleData[moduleId] = data; +/******/ +/******/ // disable module (this disables requires from this module) +/******/ module.hot.active = false; +/******/ +/******/ // remove module from cache +/******/ delete installedModules[moduleId]; +/******/ +/******/ // remove "parents" references from all children +/******/ for(j = 0; j < module.children.length; j++) { +/******/ var child = installedModules[module.children[j]]; +/******/ if(!child) continue; +/******/ idx = child.parents.indexOf(moduleId); +/******/ if(idx >= 0) { +/******/ child.parents.splice(idx, 1); +/******/ } +/******/ } +/******/ } +/******/ +/******/ // remove outdated dependency from module children +/******/ var dependency; +/******/ var moduleOutdatedDependencies; +/******/ for(moduleId in outdatedDependencies) { +/******/ if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) { +/******/ module = installedModules[moduleId]; +/******/ if(module) { +/******/ moduleOutdatedDependencies = outdatedDependencies[moduleId]; +/******/ for(j = 0; j < moduleOutdatedDependencies.length; j++) { +/******/ dependency = moduleOutdatedDependencies[j]; +/******/ idx = module.children.indexOf(dependency); +/******/ if(idx >= 0) module.children.splice(idx, 1); +/******/ } +/******/ } +/******/ } +/******/ } +/******/ +/******/ // Not in "apply" phase +/******/ hotSetStatus("apply"); +/******/ +/******/ hotCurrentHash = hotUpdateNewHash; +/******/ +/******/ // insert new code +/******/ for(moduleId in appliedUpdate) { +/******/ if(Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) { +/******/ modules[moduleId] = appliedUpdate[moduleId]; +/******/ } +/******/ } +/******/ +/******/ // call accept handlers +/******/ var error = null; +/******/ for(moduleId in outdatedDependencies) { +/******/ if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) { +/******/ module = installedModules[moduleId]; +/******/ moduleOutdatedDependencies = outdatedDependencies[moduleId]; +/******/ var callbacks = []; +/******/ for(i = 0; i < moduleOutdatedDependencies.length; i++) { +/******/ dependency = moduleOutdatedDependencies[i]; +/******/ cb = module.hot._acceptedDependencies[dependency]; +/******/ if(callbacks.indexOf(cb) >= 0) continue; +/******/ callbacks.push(cb); +/******/ } +/******/ for(i = 0; i < callbacks.length; i++) { +/******/ cb = callbacks[i]; +/******/ try { +/******/ cb(moduleOutdatedDependencies); +/******/ } catch(err) { +/******/ if(options.onErrored) { +/******/ options.onErrored({ +/******/ type: "accept-errored", +/******/ moduleId: moduleId, +/******/ dependencyId: moduleOutdatedDependencies[i], +/******/ error: err +/******/ }); +/******/ } +/******/ if(!options.ignoreErrored) { +/******/ if(!error) +/******/ error = err; +/******/ } +/******/ } +/******/ } +/******/ } +/******/ } +/******/ +/******/ // Load self accepted modules +/******/ for(i = 0; i < outdatedSelfAcceptedModules.length; i++) { +/******/ var item = outdatedSelfAcceptedModules[i]; +/******/ moduleId = item.module; +/******/ hotCurrentParents = [moduleId]; +/******/ try { +/******/ __webpack_require__(moduleId); +/******/ } catch(err) { +/******/ if(typeof item.errorHandler === "function") { +/******/ try { +/******/ item.errorHandler(err); +/******/ } catch(err2) { +/******/ if(options.onErrored) { +/******/ options.onErrored({ +/******/ type: "self-accept-error-handler-errored", +/******/ moduleId: moduleId, +/******/ error: err2, +/******/ orginalError: err +/******/ }); +/******/ } +/******/ if(!options.ignoreErrored) { +/******/ if(!error) +/******/ error = err2; +/******/ } +/******/ if(!error) +/******/ error = err; +/******/ } +/******/ } else { +/******/ if(options.onErrored) { +/******/ options.onErrored({ +/******/ type: "self-accept-errored", +/******/ moduleId: moduleId, +/******/ error: err +/******/ }); +/******/ } +/******/ if(!options.ignoreErrored) { +/******/ if(!error) +/******/ error = err; +/******/ } +/******/ } +/******/ } +/******/ } +/******/ +/******/ // handle errors in accept handlers and self accepted module load +/******/ if(error) { +/******/ hotSetStatus("fail"); +/******/ return Promise.reject(error); +/******/ } +/******/ +/******/ hotSetStatus("idle"); +/******/ return new Promise(function(resolve) { +/******/ resolve(outdatedModules); +/******/ }); +/******/ } +/******/ +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {}, +/******/ hot: hotCreateModule(moduleId), +/******/ parents: (hotCurrentParentsTemp = hotCurrentParents, hotCurrentParents = [], hotCurrentParentsTemp), +/******/ children: [] +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId)); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // identity function for calling harmony imports with the correct context +/******/ __webpack_require__.i = function(value) { return value; }; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // __webpack_hash__ +/******/ __webpack_require__.h = function() { return hotCurrentHash; }; +/******/ +/******/ // Load entry module and return exports +/******/ return hotCreateRequire(395)(__webpack_require__.s = 395); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 202: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__terms_and_conditions_option_handler__ = __webpack_require__(240); +/** + * 2007-2018 PrestaShop + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to http://www.prestashop.com for more information. + * + * @author PrestaShop SA + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + + + +var $ = window.$; + +$(function () { + new __WEBPACK_IMPORTED_MODULE_0__terms_and_conditions_option_handler__["a" /* default */](); +}); + +/***/ }), + +/***/ 240: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** + * 2007-2018 PrestaShop + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to http://www.prestashop.com for more information. + * + * @author PrestaShop SA + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +var $ = window.$; + +var TermsAndConditionsOptionHandler = function () { + function TermsAndConditionsOptionHandler() { + var _this = this; + + _classCallCheck(this, TermsAndConditionsOptionHandler); + + this.handle(); + + $('input[name="form[general][enable_tos]"]').on('change', function () { + return _this.handle(); + }); + } + + _createClass(TermsAndConditionsOptionHandler, [{ + key: 'handle', + value: function handle() { + var tosEnabledVal = $('input[name="form[general][enable_tos]"]:checked').val(); + var isTosEnabled = parseInt(tosEnabledVal); + + this.handleTermsAndConditionsCmsSelect(isTosEnabled); + } + + /** + * If terms and conditions option is disabled, then terms and conditions + * cms select must be disabled. + * + * @param {int} isTosEnabled + */ + + }, { + key: 'handleTermsAndConditionsCmsSelect', + value: function handleTermsAndConditionsCmsSelect(isTosEnabled) { + var tosCmsSelect = $('#form_general_tos_cms_id'); + + if (isTosEnabled) { + tosCmsSelect.removeAttr('disabled'); + } else { + tosCmsSelect.attr('disabled', 'disabled'); + } + } + }]); + + return TermsAndConditionsOptionHandler; +}(); + +/* harmony default export */ __webpack_exports__["a"] = (TermsAndConditionsOptionHandler); + +/***/ }), + +/***/ 395: +/***/ (function(module, exports, __webpack_require__) { + +module.exports = __webpack_require__(202); + + +/***/ }) + +/******/ }); \ No newline at end of file diff --git a/admin-dev/themes/new-theme/webpack.config.js b/admin-dev/themes/new-theme/webpack.config.js index 6590b312da8d9..cdbc27cb70067 100644 --- a/admin-dev/themes/new-theme/webpack.config.js +++ b/admin-dev/themes/new-theme/webpack.config.js @@ -55,6 +55,9 @@ let config = { logs: [ './js/app/pages/logs', ], + order_preferences: [ + './js/pages/order-preferences', + ], product_preferences: [ './js/pages/product-preferences', ], diff --git a/classes/Link.php b/classes/Link.php index e816841eddba2..b811cd2e7b0ea 100644 --- a/classes/Link.php +++ b/classes/Link.php @@ -743,6 +743,7 @@ public function getAdminLink($controller, $withToken = true, $sfRouteParams = ar 'AdminMaintenance' => 'admin_maintenance', 'AdminPPreferences' => 'admin_product_preferences', 'AdminPreferences' => 'admin_preferences', + 'AdminOrderPreferences' => 'admin_order_preferences', 'AdminCustomerPreferences' => 'admin_customer_preferences', 'AdminImport' => 'admin_import', ); diff --git a/controllers/admin/AdminOrderPreferencesController.php b/controllers/admin/AdminOrderPreferencesController.php deleted file mode 100644 index 06704df4a4891..0000000000000 --- a/controllers/admin/AdminOrderPreferencesController.php +++ /dev/null @@ -1,185 +0,0 @@ - - * @copyright 2007-2018 PrestaShop SA - * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) - * International Registered Trademark & Property of PrestaShop SA - */ - -/** - * @property Configuration $object - */ -class AdminOrderPreferencesControllerCore extends AdminController -{ - public function __construct() - { - $this->bootstrap = true; - $this->className = 'Configuration'; - $this->table = 'configuration'; - - parent::__construct(); - - // List of CMS tabs - $cms_tab = array(0 => array( - 'id' => 0, - 'name' => $this->trans('None', array(), 'Admin.Global') - )); - foreach (CMS::listCms($this->context->language->id) as $cms_file) { - $cms_tab[] = array('id' => $cms_file['id_cms'], 'name' => $cms_file['meta_title']); - } - - $this->fields_options = array( - 'general' => array( - 'title' => $this->trans('General', array(), 'Admin.Global'), - 'icon' => 'icon-cogs', - 'fields' => array( - 'PS_FINAL_SUMMARY_ENABLED' => array( - 'title' => $this->trans('Enable final summary', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Display an overview of the addresses, shipping method and cart just before the order button (required in some European countries).', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_GUEST_CHECKOUT_ENABLED' => array( - 'title' => $this->trans('Enable guest checkout', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Allow guest visitors to place an order without registering.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_DISALLOW_HISTORY_REORDERING' => array( - 'title' => $this->trans('Disable Reordering Option', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Disable the option to allow customers to reorder in one click from the order history page (required in some European countries).', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_PURCHASE_MINIMUM' => array( - 'title' => $this->trans('Minimum purchase total required in order to validate the order', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Set to 0 to disable this feature.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isFloat', - 'cast' => 'floatval', - 'type' => 'price' - ), - 'PS_ORDER_RECALCULATE_SHIPPING' => array( - 'title' => $this->trans('Recalculate shipping costs after editing the order', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Automatically updates the shipping costs when you edit an order.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_ALLOW_MULTISHIPPING' => array( - 'title' => $this->trans('Allow multishipping', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Allow the customer to ship orders to multiple addresses. This option will convert the customer\'s cart into one or more orders.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_SHIP_WHEN_AVAILABLE' => array( - 'title' => $this->trans('Delayed shipping', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Allows you to delay shipping at your customers\' request.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_CONDITIONS' => array( - 'title' => $this->trans('Terms of service', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Require customers to accept or decline terms of service before processing an order.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool', - 'js' => array( - 'on' => 'onchange="changeCMSActivationAuthorization()"', - 'off' => 'onchange="changeCMSActivationAuthorization()"' - ) - ), - 'PS_CONDITIONS_CMS_ID' => array( - 'title' => $this->trans('Page for the Terms and conditions', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Choose the page which contains your store\'s terms and conditions of use.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isInt', - 'type' => 'select', - 'list' => $cms_tab, - 'identifier' => 'id', - 'cast' => 'intval' - ) - ), - 'submit' => array('title' => $this->trans('Save', array(), 'Admin.Actions')) - ), - 'gift' => array( - 'title' => $this->trans('Gift options', array(), 'Admin.Shopparameters.Feature'), - 'icon' => 'icon-gift', - 'fields' => array( - 'PS_GIFT_WRAPPING' => array( - 'title' => $this->trans('Offer gift wrapping', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Suggest gift-wrapping to customers.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - 'PS_GIFT_WRAPPING_PRICE' => array( - 'title' => $this->trans('Gift-wrapping price', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Set a price for gift wrapping.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isPrice', - 'cast' => 'floatval', - 'type' => 'price' - ), - 'PS_GIFT_WRAPPING_TAX_RULES_GROUP' => array( - 'title' => $this->trans('Gift-wrapping tax', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Set a tax for gift wrapping.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isInt', - 'cast' => 'intval', - 'type' => 'select', - 'list' => array_merge(array(array('id_tax_rules_group' => 0, 'name' => $this->trans('None'))), TaxRulesGroup::getTaxRulesGroups(true)), - 'identifier' => 'id_tax_rules_group' - ), - 'PS_RECYCLABLE_PACK' => array( - 'title' => $this->trans('Offer recycled packaging', array(), 'Admin.Shopparameters.Feature'), - 'hint' => $this->trans('Suggest recycled packaging to customer.', array(), 'Admin.Shopparameters.Help'), - 'validation' => 'isBool', - 'cast' => 'intval', - 'type' => 'bool' - ), - ), - 'submit' => array('title' => $this->trans('Save', array(), 'Admin.Actions')), - ), - ); - - if (!Configuration::get('PS_ALLOW_MULTISHIPPING')) { - unset($this->fields_options['general']['fields']['PS_ALLOW_MULTISHIPPING']); - } - - if (Configuration::get('PS_ATCP_SHIPWRAP')) { - unset($this->fields_options['gift']['fields']['PS_GIFT_WRAPPING_TAX_RULES_GROUP']); - } - } - - /** - * This method is called before we start to update options configuration - */ - public function beforeUpdateOptions() - { - $sql = 'SELECT `id_cms` FROM `'._DB_PREFIX_.'cms` - WHERE id_cms = '.(int)Tools::getValue('PS_CONDITIONS_CMS_ID'); - if (Tools::getValue('PS_CONDITIONS') && (Tools::getValue('PS_CONDITIONS_CMS_ID') == 0 || !Db::getInstance()->getValue($sql))) { - $this->errors[] = $this->trans('Assign a valid page if you want it to be read.', array(), 'Admin.Shopparameters.Notification'); - } - } -} diff --git a/src/Adapter/CMS/CMSDataProvider.php b/src/Adapter/CMS/CMSDataProvider.php new file mode 100644 index 0000000000000..c76a737186467 --- /dev/null +++ b/src/Adapter/CMS/CMSDataProvider.php @@ -0,0 +1,77 @@ + + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace PrestaShop\PrestaShop\Adapter\CMS; + +use CMS; + +/** + * Class CMSDataProvider provides CMS data using legacy code + */ +class CMSDataProvider +{ + /** + * Gets all CMS pages + * + * @param int $languageId + * + * @return array + */ + public function getCMSPages($languageId = null) + { + return CMS::listCms($languageId); + } + + /** + * Gets one CMS object by ID + * + * @param int $cmsId + * + * @return CMS + */ + public function getCMSById($cmsId) + { + return new CMS($cmsId); + } + + /** + * Gets CMS choices for choice type + * + * @param int $languageId + * + * @return array + */ + public function getCMSChoices($languageId = null) + { + $choices = []; + + foreach ($this->getCMSPages($languageId) as $cms) { + $choices[$cms['meta_title']] = $cms['id_cms']; + } + + return $choices; + } +} diff --git a/src/Adapter/Currency/CurrencyDataProvider.php b/src/Adapter/Currency/CurrencyDataProvider.php index 3b3724457bb18..a330b88fc6cb4 100644 --- a/src/Adapter/Currency/CurrencyDataProvider.php +++ b/src/Adapter/Currency/CurrencyDataProvider.php @@ -42,4 +42,91 @@ public function getCurrencies($object = false, $active = true, $group_by = false { return Currency::getCurrencies($object = false, $active = true, $group_by = false); } + + /** + * Get a Currency entity instance by ISO code + * + * @param string $isoCode + * An ISO 4217 currency code + * + * @param int|null $idLang + * Set this parameter if you want the currency in a specific language. + * If null, default language will be used. + * + * @return Currency|null + * The asked Currency object, or null if not found. + */ + public function getCurrencyByIsoCode($isoCode, $idLang = null) + { + $currencyId = Currency::getIdByIsoCode($isoCode); + if (!$currencyId) { + return null; + } + + if (null === $idLang) { + $idLang = Configuration::get('PS_LANG_DEFAULT'); + } + + return new Currency($currencyId, $idLang); + } + + /** + * Get a Currency entity instance. + * If the passed ISO code is known, this Currency entity will be loaded with known data. + * + * @param string $isoCode + * An ISO 4217 currency code + * + * @param int|null $idLang + * Set this parameter if you want the currency in a specific language. + * If null, default language will be used. + * + * @return Currency + * The asked Currency object, loaded with relevant data if passed ISO code is known. + */ + public function getCurrencyByIsoCodeOrCreate($isoCode, $idLang = null) + { + if (null === $idLang) { + $idLang = Configuration::get('PS_LANG_DEFAULT'); + } + + $currency = $this->getCurrencyByIsoCode($isoCode, $idLang); + if (null === $currency) { + $currency = new Currency(null, $idLang); + } + + return $currency; + } + + /** + * Persists a Currency entity into DB. + * If this entity already exists in DB (has a known currency_id), it will be updated. + * + * @param Currency $currencyEntity + * Currency object model to save + * + * @throws PrestaShopException + * If something wrong happened with DB when saving $currencyEntity + * + * @throws Exception + * If an unexpected result is retrieved when saving $currencyEntity + */ + public function saveCurrency(Currency $currencyEntity) + { + if (false === $currencyEntity->save()) { + throw new Exception('Failed saving Currency entity'); + } + } + + /** + * Gets a legacy Currency instance by ID + * + * @param int $currencyId + * + * @return Currency + */ + public function getCurrencyById($currencyId) + { + return new Currency($currencyId); + } } diff --git a/src/Adapter/Order/GeneralConfiguration.php b/src/Adapter/Order/GeneralConfiguration.php new file mode 100644 index 0000000000000..00f9f4abaaadc --- /dev/null +++ b/src/Adapter/Order/GeneralConfiguration.php @@ -0,0 +1,99 @@ + + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace PrestaShop\PrestaShop\Adapter\Order; + +use PrestaShop\PrestaShop\Adapter\Configuration; +use PrestaShop\PrestaShop\Core\Configuration\DataConfigurationInterface; + +class GeneralConfiguration implements DataConfigurationInterface +{ + /** + * @var Configuration + */ + private $configuration; + + public function __construct(Configuration $configuration) + { + $this->configuration = $configuration; + } + + /** + * {@inheritdoc} + */ + public function getConfiguration() + { + return [ + 'enable_final_summary' => $this->configuration->getBoolean('PS_FINAL_SUMMARY_ENABLED'), + 'enable_guest_checkout' => $this->configuration->getBoolean('PS_GUEST_CHECKOUT_ENABLED'), + 'disable_reordering_option' => $this->configuration->getBoolean('PS_DISALLOW_HISTORY_REORDERING'), + 'purchase_minimum_value' => $this->configuration->get('PS_PURCHASE_MINIMUM'), + 'recalculate_shipping_cost' => $this->configuration->getBoolean('PS_ORDER_RECALCULATE_SHIPPING'), + 'allow_multishipping' => $this->configuration->getBoolean('PS_ALLOW_MULTISHIPPING'), + 'allow_delayed_shipping' => $this->configuration->getBoolean('PS_SHIP_WHEN_AVAILABLE'), + 'enable_tos' => $this->configuration->getBoolean('PS_CONDITIONS'), + 'tos_cms_id' => $this->configuration->get('PS_CONDITIONS_CMS_ID'), + ]; + } + + /** + * {@inheritdoc} + */ + public function updateConfiguration(array $configuration) + { + if ($this->validateConfiguration($configuration)) { + $this->configuration->set('PS_FINAL_SUMMARY_ENABLED', $configuration['enable_final_summary']); + $this->configuration->set('PS_GUEST_CHECKOUT_ENABLED', $configuration['enable_guest_checkout']); + $this->configuration->set('PS_DISALLOW_HISTORY_REORDERING', $configuration['disable_reordering_option']); + $this->configuration->set('PS_PURCHASE_MINIMUM', $configuration['purchase_minimum_value']); + $this->configuration->set('PS_ORDER_RECALCULATE_SHIPPING', $configuration['recalculate_shipping_cost']); + $this->configuration->set('PS_ALLOW_MULTISHIPPING', $configuration['allow_multishipping']); + $this->configuration->set('PS_SHIP_WHEN_AVAILABLE', $configuration['allow_delayed_shipping']); + $this->configuration->set('PS_CONDITIONS', $configuration['enable_tos']); + $this->configuration->set('PS_CONDITIONS_CMS_ID', $configuration['tos_cms_id']); + } + + return []; + } + + /** + * {@inheritdoc} + */ + public function validateConfiguration(array $configuration) + { + return isset( + $configuration['enable_final_summary'], + $configuration['enable_guest_checkout'], + $configuration['disable_reordering_option'], + $configuration['purchase_minimum_value'], + $configuration['recalculate_shipping_cost'], + $configuration['allow_multishipping'], + $configuration['allow_delayed_shipping'], + $configuration['enable_tos'], + $configuration['tos_cms_id'] + ); + } +} diff --git a/src/Adapter/Order/GiftOptionsConfiguration.php b/src/Adapter/Order/GiftOptionsConfiguration.php new file mode 100644 index 0000000000000..86b2c71c46bdb --- /dev/null +++ b/src/Adapter/Order/GiftOptionsConfiguration.php @@ -0,0 +1,84 @@ + + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace PrestaShop\PrestaShop\Adapter\Order; + +use PrestaShop\PrestaShop\Adapter\Configuration; +use PrestaShop\PrestaShop\Core\Configuration\DataConfigurationInterface; + +class GiftOptionsConfiguration implements DataConfigurationInterface +{ + /** + * @var Configuration + */ + private $configuration; + + public function __construct(Configuration $configuration) + { + $this->configuration = $configuration; + } + + /** + * {@inheritdoc} + */ + public function getConfiguration() + { + return [ + 'enable_gift_wrapping' => $this->configuration->getBoolean('PS_GIFT_WRAPPING'), + 'gift_wrapping_price' => $this->configuration->get('PS_GIFT_WRAPPING_PRICE'), + 'gift_wrapping_tax_rules_group' => $this->configuration->get('PS_GIFT_WRAPPING_TAX_RULES_GROUP'), + 'offer_recyclable_pack' => $this->configuration->getBoolean('PS_RECYCLABLE_PACK'), + ]; + } + + /** + * {@inheritdoc} + */ + public function updateConfiguration(array $configuration) + { + if ($this->validateConfiguration($configuration)) { + $this->configuration->set('PS_GIFT_WRAPPING', $configuration['enable_gift_wrapping']); + $this->configuration->set('PS_GIFT_WRAPPING_PRICE', $configuration['gift_wrapping_price']); + $this->configuration->set('PS_GIFT_WRAPPING_TAX_RULES_GROUP', $configuration['gift_wrapping_tax_rules_group']); + $this->configuration->set('PS_RECYCLABLE_PACK', $configuration['offer_recyclable_pack']); + } + + return []; + } + + /** + * {@inheritdoc} + */ + public function validateConfiguration(array $configuration) + { + return isset( + $configuration['enable_gift_wrapping'], + $configuration['gift_wrapping_price'], + $configuration['gift_wrapping_tax_rules_group'], + $configuration['offer_recyclable_pack'] + ); + } +} diff --git a/src/Adapter/Tax/TaxRuleDataProvider.php b/src/Adapter/Tax/TaxRuleDataProvider.php index b2b78e2a4567d..c87a5d234e741 100644 --- a/src/Adapter/Tax/TaxRuleDataProvider.php +++ b/src/Adapter/Tax/TaxRuleDataProvider.php @@ -108,4 +108,23 @@ public function getProductEcotaxRate() { return Tax::getProductEcotaxRate(); } + + /** + * Gets a list of tax rules groups for choice type + * + * @param bool $onlyActive if true, returns only active tax rules groups + * + * @return array + */ + public function getTaxRulesGroupChoices($onlyActive = true) + { + $taxRulesGroups = $this->getTaxRulesGroups($onlyActive); + $choices = []; + + foreach ($taxRulesGroups as $taxRulesGroup) { + $choices[$taxRulesGroup['name']] = $taxRulesGroup['id_tax_rules_group']; + } + + return $choices; + } } diff --git a/src/PrestaShopBundle/Controller/Admin/Configure/ShopParameters/OrderPreferencesController.php b/src/PrestaShopBundle/Controller/Admin/Configure/ShopParameters/OrderPreferencesController.php new file mode 100644 index 0000000000000..23e9a9af51e49 --- /dev/null +++ b/src/PrestaShopBundle/Controller/Admin/Configure/ShopParameters/OrderPreferencesController.php @@ -0,0 +1,108 @@ + + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace PrestaShopBundle\Controller\Admin\Configure\ShopParameters; + +use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController; +use PrestaShopBundle\Security\Voter\PageVoter; +use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; + +/** + * Controller responsible of "Configure > Shop Parameters > Order Settings" page + */ +class OrderPreferencesController extends FrameworkBundleAdminController +{ + /** + * Show order preferences page + * + * @param Request $request + * + * @Template("@PrestaShop/Admin/Configure/ShopParameters/OrderPreferences/order_preferences.html.twig") + * + * @return array Template parameters + */ + public function indexAction(Request $request) + { + $legacyController = $request->attributes->get('_legacy_controller'); + + $form = $this->get('prestashop.admin.order_preferences.form_handler')->getForm(); + + return [ + 'layoutTitle' => $this->trans('Order settings', 'Admin.Navigation.Menu'), + 'requireAddonsSearch' => true, + 'enableSidebar' => true, + 'help_link' => $this->generateSidebarLink($legacyController), + 'form' => $form->createView(), + 'isMultishippingEnabled' => $this->configuration->getBoolean('PS_ALLOW_MULTISHIPPING'), + 'isAtcpShipWrapEnabled' => $this->configuration->getBoolean('PS_ATCP_SHIPWRAP'), + ]; + } + + /** + * Handle order settings form submit + * + * @param Request $request + * + * @return RedirectResponse + */ + public function processAction(Request $request) + { + $legacyController = $request->attributes->get('_legacy_controller'); + + if (!in_array( + $this->authorizationLevel($legacyController), + [ + PageVoter::LEVEL_UPDATE, + PageVoter::LEVEL_CREATE, + PageVoter::LEVEL_DELETE, + ] + )) { + $this->addFlash( + 'error', + $this->trans('You do not have permission to edit this', 'Admin.Notifications.Error') + ); + + return $this->redirectToRoute('admin_order_preferences'); + } + + $formHandler = $this->get('prestashop.admin.order_preferences.form_handler'); + + $form = $formHandler->getForm(); + $form->handleRequest($request); + + if ($form->isSubmitted()) { + if ($errors = $formHandler->save($form->getData())) { + $this->flashErrors($errors); + } else { + $this->addFlash('success', $this->trans('Update successful', 'Admin.Notifications.Success')); + } + } + + return $this->redirectToRoute('admin_order_preferences'); + } +} diff --git a/src/PrestaShopBundle/Form/Admin/Configure/ShopParameters/OrderPreferences/GeneralType.php b/src/PrestaShopBundle/Form/Admin/Configure/ShopParameters/OrderPreferences/GeneralType.php new file mode 100644 index 0000000000000..3c02be140a61c --- /dev/null +++ b/src/PrestaShopBundle/Form/Admin/Configure/ShopParameters/OrderPreferences/GeneralType.php @@ -0,0 +1,119 @@ + + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace PrestaShopBundle\Form\Admin\Configure\ShopParameters\OrderPreferences; + +use PrestaShop\PrestaShop\Adapter\Configuration; +use PrestaShop\PrestaShop\Adapter\Currency\CurrencyDataProvider; +use PrestaShopBundle\Form\Admin\Type\MoneyWithSuffixType; +use PrestaShopBundle\Form\Admin\Type\SwitchType; +use PrestaShopBundle\Form\Admin\Type\TranslatorAwareType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Class generates "General" form + * in "Configure > Shop Parameters > Order Settings" page. + */ +class GeneralType extends TranslatorAwareType +{ + /** + * @var CurrencyDataProvider + */ + private $currencyDataProvider; + + /** + * CMS pages choices for Terms Of Service + * + * @var array + */ + private $tosCmsChoices; + + public function __construct( + TranslatorInterface $translator, + array $locales, + CurrencyDataProvider $currencyDataProvider, + array $tosCmsChoices + ) { + parent::__construct($translator, $locales); + + $this->currencyDataProvider = $currencyDataProvider; + $this->tosCmsChoices = $tosCmsChoices; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + /** @var Configuration $configuration */ + $configuration = $this->getConfiguration(); + $isMultishippingEnabled = $configuration->getBoolean('PS_ALLOW_MULTISHIPPING'); + $defaultCurrencyId = $configuration->getInt('PS_CURRENCY_DEFAULT'); + $defaultCurrency = $this->currencyDataProvider->getCurrencyById($defaultCurrencyId); + + $builder + ->add('enable_final_summary', SwitchType::class) + ->add('enable_guest_checkout', SwitchType::class) + ->add('disable_reordering_option', SwitchType::class) + ->add('purchase_minimum_value', MoneyWithSuffixType::class, [ + 'currency' => $defaultCurrency->iso_code, + 'suffix' => $this->trans('(tax excl.)', 'Admin.Global'), + ]) + ->add('recalculate_shipping_cost', SwitchType::class) + ; + + if ($isMultishippingEnabled) { + $builder->add('allow_multishipping', SwitchType::class); + } + + $builder + ->add('allow_delayed_shipping', SwitchType::class) + ->add('enable_tos', SwitchType::class) + ->add('tos_cms_id', ChoiceType::class, [ + 'placeholder' => $this->trans('None', 'Admin.Global'), + 'choices' => $this->tosCmsChoices, + ]) + ; + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'translation_domain' => 'Admin.Shopparameters.Feature', + ]); + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return 'order_preferences_general_block'; + } +} diff --git a/src/PrestaShopBundle/Form/Admin/Configure/ShopParameters/OrderPreferences/GiftOptionsType.php b/src/PrestaShopBundle/Form/Admin/Configure/ShopParameters/OrderPreferences/GiftOptionsType.php new file mode 100644 index 0000000000000..1f4aa3d766e60 --- /dev/null +++ b/src/PrestaShopBundle/Form/Admin/Configure/ShopParameters/OrderPreferences/GiftOptionsType.php @@ -0,0 +1,115 @@ + + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace PrestaShopBundle\Form\Admin\Configure\ShopParameters\OrderPreferences; + +use PrestaShop\PrestaShop\Adapter\Configuration; +use PrestaShop\PrestaShop\Adapter\Currency\CurrencyDataProvider; +use PrestaShopBundle\Form\Admin\Type\MoneyWithSuffixType; +use PrestaShopBundle\Form\Admin\Type\SwitchType; +use PrestaShopBundle\Form\Admin\Type\TranslatorAwareType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Class generates "Gift options" form + * in "Configure > Shop Parameters > Order Settings" page. + */ +class GiftOptionsType extends TranslatorAwareType +{ + /** + * @var CurrencyDataProvider + */ + private $currencyDataProvider; + + /** + * @var array + */ + private $taxChoices; + + public function __construct( + TranslatorInterface $translator, + array $locales, + CurrencyDataProvider $currencyDataProvider, + array $taxChoices + ) { + parent::__construct($translator, $locales); + + $this->currencyDataProvider = $currencyDataProvider; + $this->taxChoices = $taxChoices; + } + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + /** @var Configuration $configuration */ + $configuration = $this->getConfiguration(); + $atcpShipWrap = $configuration->getBoolean('PS_ATCP_SHIPWRAP'); + $defaultCurrencyId = $configuration->getInt('PS_CURRENCY_DEFAULT'); + $defaultCurrency = $this->currencyDataProvider->getCurrencyById($defaultCurrencyId); + + $builder + ->add('enable_gift_wrapping', SwitchType::class) + ->add('gift_wrapping_price', MoneyWithSuffixType::class, [ + 'required' => false, + 'currency' => $defaultCurrency->iso_code, + 'suffix' => $this->trans('(tax excl.)', 'Admin.Global'), + ]) + ; + + if (!$atcpShipWrap) { + $builder->add('gift_wrapping_tax_rules_group', ChoiceType::class, [ + 'required' => false, + 'placeholder' => $this->trans('None', 'Admin.Global'), + 'choices' => $this->taxChoices, + ]); + } + + $builder->add('offer_recyclable_pack', SwitchType::class); + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'translation_domain' => 'Admin.Shopparameters.Feature', + ]); + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return 'order_preferences_gift_options_block'; + } +} diff --git a/src/PrestaShopBundle/Form/Admin/Configure/ShopParameters/OrderPreferences/OrderPreferencesFormDataProvider.php b/src/PrestaShopBundle/Form/Admin/Configure/ShopParameters/OrderPreferences/OrderPreferencesFormDataProvider.php new file mode 100644 index 0000000000000..363d995852a6b --- /dev/null +++ b/src/PrestaShopBundle/Form/Admin/Configure/ShopParameters/OrderPreferences/OrderPreferencesFormDataProvider.php @@ -0,0 +1,167 @@ + + * @copyright 2007-2018 PrestaShop SA + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace PrestaShopBundle\Form\Admin\Configure\ShopParameters\OrderPreferences; + +use PrestaShop\PrestaShop\Adapter\CMS\CMSDataProvider; +use PrestaShop\PrestaShop\Adapter\Order\GeneralConfiguration; +use PrestaShop\PrestaShop\Adapter\Order\GiftOptionsConfiguration; +use PrestaShop\PrestaShop\Core\Form\FormDataProviderInterface; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Class is responsible of managing the data manipulated using forms + * in "Configure > Shop Parameters > Order Settings" page. + */ +class OrderPreferencesFormDataProvider implements FormDataProviderInterface +{ + /** + * @var GeneralConfiguration + */ + private $generalConfiguration; + + /** + * @var GiftOptionsConfiguration + */ + private $giftOptionsConfiguration; + + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * @var CMSDataProvider + */ + private $cmsDataProvider; + + public function __construct( + GeneralConfiguration $generalConfiguration, + GiftOptionsConfiguration $giftOptionsConfiguration, + TranslatorInterface $translator, + CMSDataProvider $cmsDataProvider + ) { + $this->generalConfiguration = $generalConfiguration; + $this->giftOptionsConfiguration = $giftOptionsConfiguration; + $this->translator = $translator; + $this->cmsDataProvider = $cmsDataProvider; + } + + /** + * {@inheritdoc} + */ + public function getData() + { + return [ + 'general' => $this->generalConfiguration->getConfiguration(), + 'gift_options' => $this->giftOptionsConfiguration->getConfiguration(), + ]; + } + + /** + * {@inheritdoc} + */ + public function setData(array $data) + { + // If TOS option is disabled - reset the cms id as well + if (!$data['general']['enable_tos']) { + $data['general']['tos_cms_id'] = 0; + } + + // If gift wrapping tax rules group was not submitted - reset it to 0 + if (!isset($data['gift_options']['gift_wrapping_tax_rules_group'])) { + $data['gift_options']['gift_wrapping_tax_rules_group'] = 0; + } + + if ($errors = $this->validate($data)) { + return $errors; + } + + return array_merge( + $this->generalConfiguration->updateConfiguration($data['general']), + $this->giftOptionsConfiguration->updateConfiguration($data['gift_options']) + ); + } + + /** + * Perform validation on form data before saving it + * + * @param array $data + * + * @return array Returns array of errors + */ + protected function validate(array $data) + { + $errors = []; + $invalidFields = []; + $purchaseMinimumValue = $data['general']['purchase_minimum_value']; + $giftWrappingPrice = $data['gift_options']['gift_wrapping_price']; + + // Check if purchase minimum value is a positive number + if (!is_numeric($purchaseMinimumValue) || $purchaseMinimumValue < 0) { + $invalidFields[] = $this->translator->trans( + 'Minimum purchase total required in order to validate the order', + [], + 'Admin.Shopparameters.Feature' + ); + } + + $isTosEnabled = $data['general']['enable_tos']; + + // If TOS option is enabled - check if the selected CMS page is valid + if ($isTosEnabled) { + $tosCmsId = $data['general']['tos_cms_id']; + $tosCms = $this->cmsDataProvider->getCMSById($tosCmsId); + + if (!$tosCms->id) { + $errors[] = [ + 'key' => 'Assign a valid page if you want it to be read.', + 'domain' => 'Admin.Shopparameters.Notification', + 'parameters' => [], + ]; + } + } + + // Check if purchase minimum value is a positive number + if (!empty($giftWrappingPrice) && (!is_numeric($giftWrappingPrice) || $giftWrappingPrice < 0)) { + $invalidFields[] = $this->translator->trans( + 'Gift-wrapping price', + [], + 'Admin.Shopparameters.Feature' + ); + } + + foreach ($invalidFields as $invalidField) { + $errors[] = [ + 'key' => 'The %s field is invalid.', + 'domain' => 'Admin.Notifications.Error', + 'parameters' => [$invalidField], + ]; + } + + return $errors; + } +} diff --git a/src/PrestaShopBundle/Form/Admin/Type/MoneyWithSuffixType.php b/src/PrestaShopBundle/Form/Admin/Type/MoneyWithSuffixType.php new file mode 100644 index 0000000000000..1326cd87bf117 --- /dev/null +++ b/src/PrestaShopBundle/Form/Admin/Type/MoneyWithSuffixType.php @@ -0,0 +1,83 @@ + + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace PrestaShopBundle\Form\Admin\Type; + +use Symfony\Component\Form\Extension\Core\Type\MoneyType; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormView; +use Symfony\Component\OptionsResolver\OptionsResolver; + +/** + * Class MoneyWithSuffixType is a money type, + * which also has a suffix string right after the currency sign + */ +class MoneyWithSuffixType extends MoneyType +{ + /** + * {@inheritdoc} + */ + public function buildView(FormView $view, FormInterface $form, array $options) + { + $pattern = self::getPattern($options['currency']); + + // Currency sign in the pattern string can be either to the left, + // or to the right of the {{ widget }}, depending on the currency. + $tokens = explode('{{ widget }}', $pattern); + + // The only non-empty token will be the currency sign - append the suffix to it + array_walk($tokens, [$this, 'applySuffix'], $options['suffix']); + + // Restore the pattern as it was before, + // just the suffix is already appended after the currency sign + $view->vars['money_pattern'] = implode('{{ widget }}', $tokens); + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + parent::configureOptions($resolver); + + $resolver->setDefault('suffix', ''); + } + + /** + * Appends the suffix to the value, if the value is not empty. + * Can be used with array_walk() + * + * @param string $value + * @param int $key not used, it's only here to make this method compatible with array_walk + * @param string $suffix + */ + private function applySuffix(&$value, $key, $suffix) + { + if (strlen($value) > 0) { + $value = rtrim($value).' '.$suffix; + } + } +} diff --git a/src/PrestaShopBundle/Resources/config/routing/admin/routing_shop_parameters.yml b/src/PrestaShopBundle/Resources/config/routing/admin/routing_shop_parameters.yml index 0c071e55c480e..c0cc9dac7fe85 100644 --- a/src/PrestaShopBundle/Resources/config/routing/admin/routing_shop_parameters.yml +++ b/src/PrestaShopBundle/Resources/config/routing/admin/routing_shop_parameters.yml @@ -13,6 +13,21 @@ admin_preferences_save: _controller: 'PrestaShopBundle:Admin\Configure\ShopParameters\Preferences:processForm' _legacy_controller: AdminPreferences +# Order Preferences +admin_order_preferences: + path: /order_preferences + methods: [GET] + defaults: + _controller: 'PrestaShopBundle:Admin\Configure\ShopParameters\OrderPreferences:index' + _legacy_controller: AdminOrderPreferences + +admin_order_preferences_save: + path: /order_preferences + methods: [POST] + defaults: + _controller: 'PrestaShopBundle:Admin\Configure\ShopParameters\OrderPreferences:process' + _legacy_controller: AdminOrderPreferences + # Maintenance admin_maintenance: path: maintenance diff --git a/src/PrestaShopBundle/Resources/config/services.yml b/src/PrestaShopBundle/Resources/config/services.yml index 433d0ca309c8d..91f6eec500e65 100644 --- a/src/PrestaShopBundle/Resources/config/services.yml +++ b/src/PrestaShopBundle/Resources/config/services.yml @@ -186,6 +186,9 @@ services: prestashop.adapter.data_provider.combination: class: PrestaShop\PrestaShop\Adapter\CombinationDataProvider + prestashop.adapter.data_provider.cms: + class: PrestaShop\PrestaShop\Adapter\CMS\CMSDataProvider + prestashop.adapter.stock_manager: class: PrestaShop\PrestaShop\Adapter\StockManager decorates: prestashop.core.data_provider.stock_interface diff --git a/src/PrestaShopBundle/Resources/config/services/adapters.yml b/src/PrestaShopBundle/Resources/config/services/adapters.yml index 8c3189894ec01..4907c51711253 100644 --- a/src/PrestaShopBundle/Resources/config/services/adapters.yml +++ b/src/PrestaShopBundle/Resources/config/services/adapters.yml @@ -142,3 +142,13 @@ services: class: 'PrestaShop\PrestaShop\Adapter\Customer\CustomerConfiguration' arguments: - '@prestashop.adapter.legacy.configuration' + + prestashop.adapter.order_general.configuration: + class: 'PrestaShop\PrestaShop\Adapter\Order\GeneralConfiguration' + arguments: + - '@prestashop.adapter.legacy.configuration' + + prestashop.adapter.order_gift.configuration: + class: 'PrestaShop\PrestaShop\Adapter\Order\GiftOptionsConfiguration' + arguments: + - '@prestashop.adapter.legacy.configuration' diff --git a/src/PrestaShopBundle/Resources/config/services/form/form_data_provider.yml b/src/PrestaShopBundle/Resources/config/services/form/form_data_provider.yml index a5c5b1447c819..195dd75608a31 100644 --- a/src/PrestaShopBundle/Resources/config/services/form/form_data_provider.yml +++ b/src/PrestaShopBundle/Resources/config/services/form/form_data_provider.yml @@ -8,6 +8,14 @@ services: - '@prestashop.adapter.customer.customer_configuration' - '@translator' + prestashop.admin.order_preferences.data_provider: + class: 'PrestaShopBundle\Form\Admin\Configure\ShopParameters\OrderPreferences\OrderPreferencesFormDataProvider' + arguments: + - '@prestashop.adapter.order_general.configuration' + - '@prestashop.adapter.order_gift.configuration' + - '@translator' + - '@prestashop.adapter.data_provider.cms' + prestashop.admin.product_preferences.data_provider: class: 'PrestaShopBundle\Form\Admin\Configure\ShopParameters\ProductPreferences\ProductPreferencesFormDataProvider' arguments: diff --git a/src/PrestaShopBundle/Resources/config/services/form/form_handler.yml b/src/PrestaShopBundle/Resources/config/services/form/form_handler.yml index 46b83235d6c06..4058b895f9bdf 100644 --- a/src/PrestaShopBundle/Resources/config/services/form/form_handler.yml +++ b/src/PrestaShopBundle/Resources/config/services/form/form_handler.yml @@ -50,6 +50,17 @@ services: 'general': 'PrestaShopBundle\Form\Admin\Configure\ShopParameters\CustomerPreferences\GeneralType' - 'CustomerPreferencesPage' + prestashop.admin.order_preferences.form_handler: + class: 'PrestaShop\PrestaShop\Core\Form\FormHandler' + arguments: + - '@=service("form.factory").createBuilder()' + - '@prestashop.hook.dispatcher' + - '@prestashop.admin.order_preferences.data_provider' + - + 'general': 'PrestaShopBundle\Form\Admin\Configure\ShopParameters\OrderPreferences\GeneralType' + 'gift_options': 'PrestaShopBundle\Form\Admin\Configure\ShopParameters\OrderPreferences\GiftOptionsType' + - 'OrderPreferencesPage' + prestashop.admin.product_preferences.form_handler: class: 'PrestaShopBundle\Form\Admin\Configure\ShopParameters\ProductPreferences\ProductPreferencesFormHandler' arguments: diff --git a/src/PrestaShopBundle/Resources/config/services/form/form_type.yml b/src/PrestaShopBundle/Resources/config/services/form/form_type.yml index 62535b9c07c8c..711893b855bcd 100644 --- a/src/PrestaShopBundle/Resources/config/services/form/form_type.yml +++ b/src/PrestaShopBundle/Resources/config/services/form/form_type.yml @@ -334,6 +334,26 @@ services: tags: - { name: form.type } + form.type.order_preferences.general: + class: 'PrestaShopBundle\Form\Admin\Configure\ShopParameters\OrderPreferences\GeneralType' + parent: 'form.type.translatable.aware' + public: true + arguments: + - '@prestashop.adapter.data_provider.currency' + - '@=service("prestashop.adapter.data_provider.cms").getCmsChoices()' + tags: + - { name: form.type } + + form.type.order_preferences.gift_options: + class: 'PrestaShopBundle\Form\Admin\Configure\ShopParameters\OrderPreferences\GiftOptionsType' + parent: 'form.type.translatable.aware' + public: true + arguments: + - '@prestashop.adapter.data_provider.currency' + - '@=service("prestashop.adapter.data_provider.tax").getTaxRulesGroupChoices()' + tags: + - { name: form.type } + form.type.import.import: class: 'PrestaShopBundle\Form\Admin\Configure\AdvancedParameters\Import\ImportType' parent: 'form.type.translatable.aware' diff --git a/src/PrestaShopBundle/Resources/views/Admin/Configure/ShopParameters/OrderPreferences/Blocks/order_preferences_general.html.twig b/src/PrestaShopBundle/Resources/views/Admin/Configure/ShopParameters/OrderPreferences/Blocks/order_preferences_general.html.twig new file mode 100644 index 0000000000000..ce40ab6cce22b --- /dev/null +++ b/src/PrestaShopBundle/Resources/views/Admin/Configure/ShopParameters/OrderPreferences/Blocks/order_preferences_general.html.twig @@ -0,0 +1,92 @@ +{#** + * 2007-2018 PrestaShop + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to http://www.prestashop.com for more information. + * + * @author PrestaShop SA + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + *#} + +{% trans_default_domain "Admin.Shopparameters.Feature" %} + +{% block order_preferences_general %} +
+
+

+ settings {{ 'General'|trans({}, 'Admin.Global') }} +

+
+
+
+ {{ ps.label_with_help(('Enable final summary'|trans), ('Display an overview of the addresses, shipping method and cart just before the order button (required in some European countries).'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(generalForm.enable_final_summary) }} + {{ form_widget(generalForm.enable_final_summary) }} +
+
+ {{ ps.label_with_help(('Enable guest checkout'|trans), ('Allow guest visitors to place an order without registering.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(generalForm.enable_guest_checkout) }} + {{ form_widget(generalForm.enable_guest_checkout) }} +
+
+ {{ ps.label_with_help(('Disable Reordering Option'|trans), ('Disable the option to allow customers to reorder in one click from the order history page (required in some European countries).'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(generalForm.disable_reordering_option) }} + {{ form_widget(generalForm.disable_reordering_option) }} +
+
+ {{ ps.label_with_help(('Minimum purchase total required in order to validate the order'|trans), ('Set to 0 to disable this feature.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(generalForm.purchase_minimum_value) }} + {{ form_widget(generalForm.purchase_minimum_value) }} +
+
+ {{ ps.label_with_help(('Recalculate shipping costs after editing the order'|trans), ('Automatically updates the shipping costs when you edit an order.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(generalForm.recalculate_shipping_cost) }} + {{ form_widget(generalForm.recalculate_shipping_cost) }} +
+ {% if isMultishippingEnabled %} +
+ {{ ps.label_with_help(('Allow multishipping'|trans), ('Allow the customer to ship orders to multiple addresses. This option will convert the customer\'s cart into one or more orders.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(generalForm.allow_multishipping) }} + {{ form_widget(generalForm.allow_multishipping) }} +
+ {% endif %} +
+ {{ ps.label_with_help(('Delayed shipping'|trans), ('Allows you to delay shipping at your customers\' request.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(generalForm.allow_delayed_shipping) }} + {{ form_widget(generalForm.allow_delayed_shipping) }} +
+
+ {{ ps.label_with_help(('Terms of service'|trans), ('Require customers to accept or decline terms of service before processing an order.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(generalForm.enable_tos) }} + {{ form_widget(generalForm.enable_tos) }} +
+
+ {{ ps.label_with_help(('Page for the Terms and conditions'|trans), ('Choose the page which contains your store\'s terms and conditions of use.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(generalForm.tos_cms_id) }} + {{ form_widget(generalForm.tos_cms_id) }} +
+
+
+ +
+
+{% endblock %} diff --git a/src/PrestaShopBundle/Resources/views/Admin/Configure/ShopParameters/OrderPreferences/Blocks/order_preferences_gift_options.html.twig b/src/PrestaShopBundle/Resources/views/Admin/Configure/ShopParameters/OrderPreferences/Blocks/order_preferences_gift_options.html.twig new file mode 100644 index 0000000000000..0ffd3a771093c --- /dev/null +++ b/src/PrestaShopBundle/Resources/views/Admin/Configure/ShopParameters/OrderPreferences/Blocks/order_preferences_gift_options.html.twig @@ -0,0 +1,69 @@ +{#** + * 2007-2018 PrestaShop + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to http://www.prestashop.com for more information. + * + * @author PrestaShop SA + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + *#} + +{% trans_default_domain "Admin.Shopparameters.Feature" %} + +{% block order_preferences_gift_options %} +
+
+

+ cake {{ 'Gift options'|trans({}, 'Admin.Global') }} +

+
+
+
+ {{ ps.label_with_help(('Offer gift wrapping'|trans), ('Suggest gift-wrapping to customers.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(giftOptionsForm.enable_gift_wrapping) }} + {{ form_widget(giftOptionsForm.enable_gift_wrapping) }} +
+
+ {{ ps.label_with_help(('Gift-wrapping price'|trans), ('Set a price for gift wrapping.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(giftOptionsForm.gift_wrapping_price) }} + {{ form_widget(giftOptionsForm.gift_wrapping_price) }} +
+ + {% if not isAtcpShipWrapEnabled %} +
+ {{ ps.label_with_help(('Gift-wrapping tax'|trans), ('Set a tax for gift wrapping.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(giftOptionsForm.gift_wrapping_tax_rules_group) }} + {{ form_widget(giftOptionsForm.gift_wrapping_tax_rules_group) }} +
+ {% endif %} + +
+ {{ ps.label_with_help(('Offer recycled packaging'|trans), ('Suggest recycled packaging to customer.'|trans({}, 'Admin.Shopparameters.Help'))) }} + {{ form_errors(giftOptionsForm.offer_recyclable_pack) }} + {{ form_widget(giftOptionsForm.offer_recyclable_pack) }} +
+
+
+ +
+
+{% endblock %} diff --git a/src/PrestaShopBundle/Resources/views/Admin/Configure/ShopParameters/OrderPreferences/order_preferences.html.twig b/src/PrestaShopBundle/Resources/views/Admin/Configure/ShopParameters/OrderPreferences/order_preferences.html.twig new file mode 100644 index 0000000000000..b6c48480a4803 --- /dev/null +++ b/src/PrestaShopBundle/Resources/views/Admin/Configure/ShopParameters/OrderPreferences/order_preferences.html.twig @@ -0,0 +1,48 @@ +{#** + * 2007-2018 PrestaShop + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * https://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@prestashop.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade PrestaShop to newer + * versions in the future. If you wish to customize PrestaShop for your + * needs please refer to http://www.prestashop.com for more information. + * + * @author PrestaShop SA + * @copyright 2007-2018 PrestaShop SA + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + *#} +{% extends '@PrestaShop/Admin/layout.html.twig' %} +{% trans_default_domain "Admin.Shopparameters.Feature" %} + +{% set generalForm, giftOptionsForm = form.general, form.gift_options %} + +{% block content %} +
+ {{ form_start(form, {'attr': {'class': 'form', 'id': 'configuration_form'}}) }} +
+ {# General options block #} + {% include '@PrestaShop/Admin/Configure/ShopParameters/OrderPreferences/Blocks/order_preferences_general.html.twig' %} + + {# Gift options block #} + {% include '@PrestaShop/Admin/Configure/ShopParameters/OrderPreferences/Blocks/order_preferences_gift_options.html.twig' %} +
+ {{ form_end(form) }} +
+{% endblock %} + +{% block javascripts %} + {{ parent() }} + + +{% endblock %} diff --git a/tests/PrestaShopBundle/Controller/ControllerTest.php b/tests/PrestaShopBundle/Controller/ControllerTest.php index 293d5063757ff..c2242a54b51f7 100644 --- a/tests/PrestaShopBundle/Controller/ControllerTest.php +++ b/tests/PrestaShopBundle/Controller/ControllerTest.php @@ -120,7 +120,6 @@ public function getControllersClasses() array('AdminOrderMessageController'), array('AdminSearchEnginesController'), array('AdminGendersController'), - array('AdminOrderPreferencesController'), array('AdminShippingController'), array('AdminTagsController'), array('AdminGeolocationController'),