Page Builder by SiteOrigin - Version 2.10.7

Version Description

  • 20 August 2019 =
  • Added setting for mobile specific margin.
  • Prevent Welcome Page Redirect During Bulk Install and TGMPA
  • Added support for password settings field.
  • Layout Block: Add filter to control whether Add Layout Block button is shown or not.
  • Fixed issue with widget duplication after moving a widget.
  • Fixed Read More Custom Text issue.
Download this release

Release Info

Developer gpriday
Plugin Icon 128x128 Page Builder by SiteOrigin
Version 2.10.7
Comparing to
See all releases

Code changes from version 2.10.6 to 2.10.7

compat/js/siteorigin-panels-layout-block.js CHANGED
@@ -1,352 +1,352 @@
1
- "use strict";
2
-
3
- function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
-
5
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
-
7
- 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); } }
8
-
9
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
10
-
11
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
12
-
13
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
14
-
15
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
16
-
17
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
18
-
19
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
20
-
21
- var _lodash = lodash,
22
- isEqual = _lodash.isEqual,
23
- debounce = _lodash.debounce,
24
- isEmpty = _lodash.isEmpty,
25
- isFunction = _lodash.isFunction;
26
- var registerBlockType = wp.blocks.registerBlockType;
27
- var _wp$element = wp.element,
28
- Component = _wp$element.Component,
29
- Fragment = _wp$element.Fragment,
30
- RawHTML = _wp$element.RawHTML,
31
- createRef = _wp$element.createRef;
32
- var BlockControls = wp.editor.BlockControls;
33
- var _wp$components = wp.components,
34
- Toolbar = _wp$components.Toolbar,
35
- IconButton = _wp$components.IconButton,
36
- Spinner = _wp$components.Spinner;
37
- var __ = wp.i18n.__;
38
- var _window = window,
39
- soPanelsBlockEditorAdmin = _window.soPanelsBlockEditorAdmin;
40
-
41
- var SiteOriginPanelsLayoutBlock =
42
- /*#__PURE__*/
43
- function (_Component) {
44
- _inherits(SiteOriginPanelsLayoutBlock, _Component);
45
-
46
- function SiteOriginPanelsLayoutBlock(props) {
47
- var _this;
48
-
49
- _classCallCheck(this, SiteOriginPanelsLayoutBlock);
50
-
51
- _this = _possibleConstructorReturn(this, _getPrototypeOf(SiteOriginPanelsLayoutBlock).call(this, props));
52
- var editMode = soPanelsBlockEditorAdmin.defaultMode === 'edit' || isEmpty(props.panelsData);
53
- _this.state = {
54
- editing: editMode,
55
- loadingPreview: !editMode,
56
- previewHtml: ''
57
- };
58
- _this.panelsContainer = createRef();
59
- _this.previewContainer = createRef();
60
- _this.panelsInitialized = false;
61
- _this.previewInitialized = false;
62
- return _this;
63
- }
64
-
65
- _createClass(SiteOriginPanelsLayoutBlock, [{
66
- key: "componentDidMount",
67
- value: function componentDidMount() {
68
- this.isStillMounted = true;
69
-
70
- if (this.state.editing) {
71
- this.setupPanels();
72
- } else if (!this.state.editing && !this.previewInitialized) {
73
- this.fetchPreview(this.props);
74
- this.fetchPreview = debounce(this.fetchPreview, 500);
75
- }
76
- }
77
- }, {
78
- key: "componentWillUnmount",
79
- value: function componentWillUnmount() {
80
- this.isStillMounted = false;
81
-
82
- if (this.builderView) {
83
- this.builderView.off('content_change');
84
- }
85
- }
86
- }, {
87
- key: "componentDidUpdate",
88
- value: function componentDidUpdate(prevProps) {
89
- // let propsChanged = !isEqual( prevProps.panelsData, this.props.panelsData );
90
- if (this.state.editing && !this.panelsInitialized) {
91
- this.setupPanels();
92
- } else if (this.state.loadingPreview) {
93
- this.fetchPreview(this.props);
94
- } else if (!this.previewInitialized && this.previewContainer.current) {
95
- jQuery(document).trigger('panels_setup_preview');
96
- this.previewInitialized = true;
97
- }
98
- }
99
- }, {
100
- key: "setupPanels",
101
- value: function setupPanels() {
102
- var _this2 = this;
103
-
104
- var $panelsContainer = jQuery(this.panelsContainer.current);
105
- var config = {
106
- editorType: 'standalone'
107
- };
108
- var builderModel = new panels.model.builder();
109
- this.builderView = new panels.view.builder({
110
- model: builderModel,
111
- config: config
112
- }); // Make sure panelsData is defined and clone so that we don't alter the underlying attribute.
113
-
114
- var panelsData = JSON.parse(JSON.stringify(jQuery.extend({}, this.props.panelsData))); // Disable block selection while dragging rows or widgets.
115
-
116
- var rowOrWidgetMouseDown = function rowOrWidgetMouseDown() {
117
- if (isFunction(_this2.props.onRowOrWidgetMouseDown)) {
118
- _this2.props.onRowOrWidgetMouseDown();
119
- }
120
-
121
- var rowOrWidgetMouseUp = function rowOrWidgetMouseUp() {
122
- jQuery(document).off('mouseup', rowOrWidgetMouseUp);
123
-
124
- if (isFunction(_this2.props.onRowOrWidgetMouseUp)) {
125
- _this2.props.onRowOrWidgetMouseUp();
126
- }
127
- };
128
-
129
- jQuery(document).on('mouseup', rowOrWidgetMouseUp);
130
- };
131
-
132
- this.builderView.on('row_added', function () {
133
- _this2.builderView.$('.so-row-move').off('mousedown', rowOrWidgetMouseDown);
134
-
135
- _this2.builderView.$('.so-row-move').on('mousedown', rowOrWidgetMouseDown);
136
-
137
- _this2.builderView.$('.so-widget').off('mousedown', rowOrWidgetMouseDown);
138
-
139
- _this2.builderView.$('.so-widget').on('mousedown', rowOrWidgetMouseDown);
140
- });
141
- this.builderView.on('widget_added', function () {
142
- _this2.builderView.$('.so-widget').off('mousedown', rowOrWidgetMouseDown);
143
-
144
- _this2.builderView.$('.so-widget').on('mousedown', rowOrWidgetMouseDown);
145
- });
146
- this.builderView.render().attach({
147
- container: $panelsContainer
148
- }).setData(panelsData);
149
- this.builderView.trigger('builder_resize');
150
- this.builderView.on('content_change', function () {
151
- var newPanelsData = _this2.builderView.getData();
152
-
153
- _this2.panelsDataChanged = !isEqual(panelsData, newPanelsData);
154
-
155
- if (_this2.panelsDataChanged) {
156
- if (_this2.props.onContentChange && isFunction(_this2.props.onContentChange)) {
157
- _this2.props.onContentChange(newPanelsData);
158
- }
159
-
160
- _this2.setState({
161
- loadingPreview: true,
162
- previewHtml: ''
163
- });
164
- }
165
- });
166
- jQuery(document).trigger('panels_setup', this.builderView);
167
- this.panelsInitialized = true;
168
- }
169
- }, {
170
- key: "fetchPreview",
171
- value: function fetchPreview(props) {
172
- var _this3 = this;
173
-
174
- if (!this.isStillMounted) {
175
- return;
176
- }
177
-
178
- this.previewInitialized = false;
179
- var fetchRequest = this.currentFetchRequest = jQuery.post({
180
- url: soPanelsBlockEditorAdmin.previewUrl,
181
- data: {
182
- action: 'so_panels_layout_block_preview',
183
- panelsData: JSON.stringify(props.panelsData)
184
- }
185
- }).then(function (preview) {
186
- if (_this3.isStillMounted && fetchRequest === _this3.currentFetchRequest && preview) {
187
- _this3.setState({
188
- previewHtml: preview,
189
- loadingPreview: false
190
- });
191
- }
192
- });
193
- return fetchRequest;
194
- }
195
- }, {
196
- key: "render",
197
- value: function render() {
198
- var _this4 = this;
199
-
200
- var panelsData = this.props.panelsData;
201
-
202
- var switchToEditing = function switchToEditing() {
203
- _this4.panelsInitialized = false;
204
-
205
- _this4.setState({
206
- editing: true
207
- });
208
- };
209
-
210
- var switchToPreview = function switchToPreview() {
211
- if (panelsData) {
212
- _this4.setState({
213
- editing: false
214
- });
215
- }
216
- };
217
-
218
- if (this.state.editing) {
219
- return React.createElement(Fragment, null, React.createElement(BlockControls, null, React.createElement(Toolbar, null, React.createElement(IconButton, {
220
- icon: "visibility",
221
- className: "components-icon-button components-toolbar__control",
222
- label: __('Preview layout.', 'siteorigin-panels'),
223
- onClick: switchToPreview
224
- }))), React.createElement("div", {
225
- key: "layout-block",
226
- className: "siteorigin-panels-layout-block-container",
227
- ref: this.panelsContainer
228
- }));
229
- } else {
230
- var loadingPreview = this.state.loadingPreview;
231
- return React.createElement(Fragment, null, React.createElement(BlockControls, null, React.createElement(Toolbar, null, React.createElement(IconButton, {
232
- icon: "edit",
233
- className: "components-icon-button components-toolbar__control",
234
- label: __('Edit layout.', 'siteorigin-panels'),
235
- onClick: switchToEditing
236
- }))), React.createElement("div", {
237
- key: "preview",
238
- className: "so-panels-block-layout-preview-container"
239
- }, loadingPreview ? React.createElement("div", {
240
- className: "so-panels-spinner-container"
241
- }, React.createElement("span", null, React.createElement(Spinner, null))) : React.createElement("div", {
242
- className: "so-panels-raw-html-container",
243
- ref: this.previewContainer
244
- }, React.createElement(RawHTML, null, this.state.previewHtml))));
245
- }
246
- }
247
- }]);
248
-
249
- return SiteOriginPanelsLayoutBlock;
250
- }(Component);
251
-
252
- registerBlockType('siteorigin-panels/layout-block', {
253
- title: __('SiteOrigin Layout', 'siteorigin-panels'),
254
- description: __("Build a layout using SiteOrigin's Page Builder.", 'siteorigin-panels'),
255
- icon: function icon() {
256
- return React.createElement("span", {
257
- className: "siteorigin-panels-block-icon"
258
- });
259
- },
260
- category: 'layout',
261
- keywords: ['page builder', 'column,grid', 'panel'],
262
- supports: {
263
- html: false
264
- },
265
- attributes: {
266
- panelsData: {
267
- type: 'object'
268
- }
269
- },
270
- edit: function edit(_ref) {
271
- var attributes = _ref.attributes,
272
- setAttributes = _ref.setAttributes,
273
- toggleSelection = _ref.toggleSelection;
274
-
275
- var onLayoutBlockContentChange = function onLayoutBlockContentChange(newPanelsData) {
276
- if (!_.isEmpty(newPanelsData.widgets)) {
277
- // Send panelsData to server for sanitization.
278
- jQuery.post(soPanelsBlockEditorAdmin.sanitizeUrl, {
279
- action: 'so_panels_layout_block_sanitize',
280
- panelsData: JSON.stringify(newPanelsData)
281
- }, function (sanitizedPanelsData) {
282
- if (sanitizedPanelsData !== '') {
283
- setAttributes({
284
- panelsData: sanitizedPanelsData
285
- });
286
- }
287
- });
288
- }
289
- };
290
-
291
- var disableSelection = function disableSelection() {
292
- toggleSelection(false);
293
- };
294
-
295
- var enableSelection = function enableSelection() {
296
- toggleSelection(true);
297
- };
298
-
299
- return React.createElement(SiteOriginPanelsLayoutBlock, {
300
- panelsData: attributes.panelsData,
301
- onContentChange: onLayoutBlockContentChange,
302
- onRowOrWidgetMouseDown: disableSelection,
303
- onRowOrWidgetMouseUp: enableSelection
304
- });
305
- },
306
- save: function save() {
307
- // Render in PHP
308
- return null;
309
- }
310
- });
311
-
312
- (function (jQuery) {
313
- if (soPanelsBlockEditorAdmin.showAddButton) {
314
- jQuery(function () {
315
- setTimeout(function () {
316
- var editorDispatch = wp.data.dispatch('core/editor');
317
- var editorSelect = wp.data.select('core/editor');
318
- var tmpl = jQuery('#siteorigin-panels-add-layout-block-button').html();
319
- var $addButton = jQuery(tmpl).insertAfter('.editor-writing-flow > div:first');
320
- $addButton.on('click', function () {
321
- var layoutBlock = wp.blocks.createBlock('siteorigin-panels/layout-block', {});
322
- var isEmpty = editorSelect.isEditedPostEmpty();
323
-
324
- if (isEmpty) {
325
- var blocks = editorSelect.getBlocks();
326
-
327
- if (blocks.length) {
328
- editorDispatch.replaceBlock(blocks[0].clientId, layoutBlock);
329
- } else {
330
- editorDispatch.insertBlock(layoutBlock);
331
- }
332
- } else {
333
- editorDispatch.insertBlock(layoutBlock);
334
- }
335
- });
336
-
337
- var hideButtonIfBlocks = function hideButtonIfBlocks() {
338
- var isEmpty = wp.data.select('core/editor').isEditedPostEmpty();
339
-
340
- if (isEmpty) {
341
- $addButton.show();
342
- } else {
343
- $addButton.hide();
344
- }
345
- };
346
-
347
- wp.data.subscribe(hideButtonIfBlocks);
348
- hideButtonIfBlocks();
349
- }, 100);
350
- });
351
- }
352
  })(jQuery);
1
+ "use strict";
2
+
3
+ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
+
5
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
+
7
+ 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); } }
8
+
9
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
10
+
11
+ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
12
+
13
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
14
+
15
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
16
+
17
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
18
+
19
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
20
+
21
+ var _lodash = lodash,
22
+ isEqual = _lodash.isEqual,
23
+ debounce = _lodash.debounce,
24
+ isEmpty = _lodash.isEmpty,
25
+ isFunction = _lodash.isFunction;
26
+ var registerBlockType = wp.blocks.registerBlockType;
27
+ var _wp$element = wp.element,
28
+ Component = _wp$element.Component,
29
+ Fragment = _wp$element.Fragment,
30
+ RawHTML = _wp$element.RawHTML,
31
+ createRef = _wp$element.createRef;
32
+ var BlockControls = wp.editor.BlockControls;
33
+ var _wp$components = wp.components,
34
+ Toolbar = _wp$components.Toolbar,
35
+ IconButton = _wp$components.IconButton,
36
+ Spinner = _wp$components.Spinner;
37
+ var __ = wp.i18n.__;
38
+ var _window = window,
39
+ soPanelsBlockEditorAdmin = _window.soPanelsBlockEditorAdmin;
40
+
41
+ var SiteOriginPanelsLayoutBlock =
42
+ /*#__PURE__*/
43
+ function (_Component) {
44
+ _inherits(SiteOriginPanelsLayoutBlock, _Component);
45
+
46
+ function SiteOriginPanelsLayoutBlock(props) {
47
+ var _this;
48
+
49
+ _classCallCheck(this, SiteOriginPanelsLayoutBlock);
50
+
51
+ _this = _possibleConstructorReturn(this, _getPrototypeOf(SiteOriginPanelsLayoutBlock).call(this, props));
52
+ var editMode = soPanelsBlockEditorAdmin.defaultMode === 'edit' || isEmpty(props.panelsData);
53
+ _this.state = {
54
+ editing: editMode,
55
+ loadingPreview: !editMode,
56
+ previewHtml: ''
57
+ };
58
+ _this.panelsContainer = createRef();
59
+ _this.previewContainer = createRef();
60
+ _this.panelsInitialized = false;
61
+ _this.previewInitialized = false;
62
+ return _this;
63
+ }
64
+
65
+ _createClass(SiteOriginPanelsLayoutBlock, [{
66
+ key: "componentDidMount",
67
+ value: function componentDidMount() {
68
+ this.isStillMounted = true;
69
+
70
+ if (this.state.editing) {
71
+ this.setupPanels();
72
+ } else if (!this.state.editing && !this.previewInitialized) {
73
+ this.fetchPreview(this.props);
74
+ this.fetchPreview = debounce(this.fetchPreview, 500);
75
+ }
76
+ }
77
+ }, {
78
+ key: "componentWillUnmount",
79
+ value: function componentWillUnmount() {
80
+ this.isStillMounted = false;
81
+
82
+ if (this.builderView) {
83
+ this.builderView.off('content_change');
84
+ }
85
+ }
86
+ }, {
87
+ key: "componentDidUpdate",
88
+ value: function componentDidUpdate(prevProps) {
89
+ // let propsChanged = !isEqual( prevProps.panelsData, this.props.panelsData );
90
+ if (this.state.editing && !this.panelsInitialized) {
91
+ this.setupPanels();
92
+ } else if (this.state.loadingPreview) {
93
+ this.fetchPreview(this.props);
94
+ } else if (!this.previewInitialized && this.previewContainer.current) {
95
+ jQuery(document).trigger('panels_setup_preview');
96
+ this.previewInitialized = true;
97
+ }
98
+ }
99
+ }, {
100
+ key: "setupPanels",
101
+ value: function setupPanels() {
102
+ var _this2 = this;
103
+
104
+ var $panelsContainer = jQuery(this.panelsContainer.current);
105
+ var config = {
106
+ editorType: 'standalone'
107
+ };
108
+ var builderModel = new panels.model.builder();
109
+ this.builderView = new panels.view.builder({
110
+ model: builderModel,
111
+ config: config
112
+ }); // Make sure panelsData is defined and clone so that we don't alter the underlying attribute.
113
+
114
+ var panelsData = JSON.parse(JSON.stringify(jQuery.extend({}, this.props.panelsData))); // Disable block selection while dragging rows or widgets.
115
+
116
+ var rowOrWidgetMouseDown = function rowOrWidgetMouseDown() {
117
+ if (isFunction(_this2.props.onRowOrWidgetMouseDown)) {
118
+ _this2.props.onRowOrWidgetMouseDown();
119
+ }
120
+
121
+ var rowOrWidgetMouseUp = function rowOrWidgetMouseUp() {
122
+ jQuery(document).off('mouseup', rowOrWidgetMouseUp);
123
+
124
+ if (isFunction(_this2.props.onRowOrWidgetMouseUp)) {
125
+ _this2.props.onRowOrWidgetMouseUp();
126
+ }
127
+ };
128
+
129
+ jQuery(document).on('mouseup', rowOrWidgetMouseUp);
130
+ };
131
+
132
+ this.builderView.on('row_added', function () {
133
+ _this2.builderView.$('.so-row-move').off('mousedown', rowOrWidgetMouseDown);
134
+
135
+ _this2.builderView.$('.so-row-move').on('mousedown', rowOrWidgetMouseDown);
136
+
137
+ _this2.builderView.$('.so-widget').off('mousedown', rowOrWidgetMouseDown);
138
+
139
+ _this2.builderView.$('.so-widget').on('mousedown', rowOrWidgetMouseDown);
140
+ });
141
+ this.builderView.on('widget_added', function () {
142
+ _this2.builderView.$('.so-widget').off('mousedown', rowOrWidgetMouseDown);
143
+
144
+ _this2.builderView.$('.so-widget').on('mousedown', rowOrWidgetMouseDown);
145
+ });
146
+ this.builderView.render().attach({
147
+ container: $panelsContainer
148
+ }).setData(panelsData);
149
+ this.builderView.trigger('builder_resize');
150
+ this.builderView.on('content_change', function () {
151
+ var newPanelsData = _this2.builderView.getData();
152
+
153
+ _this2.panelsDataChanged = !isEqual(panelsData, newPanelsData);
154
+
155
+ if (_this2.panelsDataChanged) {
156
+ if (_this2.props.onContentChange && isFunction(_this2.props.onContentChange)) {
157
+ _this2.props.onContentChange(newPanelsData);
158
+ }
159
+
160
+ _this2.setState({
161
+ loadingPreview: true,
162
+ previewHtml: ''
163
+ });
164
+ }
165
+ });
166
+ jQuery(document).trigger('panels_setup', this.builderView);
167
+ this.panelsInitialized = true;
168
+ }
169
+ }, {
170
+ key: "fetchPreview",
171
+ value: function fetchPreview(props) {
172
+ var _this3 = this;
173
+
174
+ if (!this.isStillMounted) {
175
+ return;
176
+ }
177
+
178
+ this.previewInitialized = false;
179
+ var fetchRequest = this.currentFetchRequest = jQuery.post({
180
+ url: soPanelsBlockEditorAdmin.previewUrl,
181
+ data: {
182
+ action: 'so_panels_layout_block_preview',
183
+ panelsData: JSON.stringify(props.panelsData)
184
+ }
185
+ }).then(function (preview) {
186
+ if (_this3.isStillMounted && fetchRequest === _this3.currentFetchRequest && preview) {
187
+ _this3.setState({
188
+ previewHtml: preview,
189
+ loadingPreview: false
190
+ });
191
+ }
192
+ });
193
+ return fetchRequest;
194
+ }
195
+ }, {
196
+ key: "render",
197
+ value: function render() {
198
+ var _this4 = this;
199
+
200
+ var panelsData = this.props.panelsData;
201
+
202
+ var switchToEditing = function switchToEditing() {
203
+ _this4.panelsInitialized = false;
204
+
205
+ _this4.setState({
206
+ editing: true
207
+ });
208
+ };
209
+
210
+ var switchToPreview = function switchToPreview() {
211
+ if (panelsData) {
212
+ _this4.setState({
213
+ editing: false
214
+ });
215
+ }
216
+ };
217
+
218
+ if (this.state.editing) {
219
+ return React.createElement(Fragment, null, React.createElement(BlockControls, null, React.createElement(Toolbar, null, React.createElement(IconButton, {
220
+ icon: "visibility",
221
+ className: "components-icon-button components-toolbar__control",
222
+ label: __('Preview layout.', 'siteorigin-panels'),
223
+ onClick: switchToPreview
224
+ }))), React.createElement("div", {
225
+ key: "layout-block",
226
+ className: "siteorigin-panels-layout-block-container",
227
+ ref: this.panelsContainer
228
+ }));
229
+ } else {
230
+ var loadingPreview = this.state.loadingPreview;
231
+ return React.createElement(Fragment, null, React.createElement(BlockControls, null, React.createElement(Toolbar, null, React.createElement(IconButton, {
232
+ icon: "edit",
233
+ className: "components-icon-button components-toolbar__control",
234
+ label: __('Edit layout.', 'siteorigin-panels'),
235
+ onClick: switchToEditing
236
+ }))), React.createElement("div", {
237
+ key: "preview",
238
+ className: "so-panels-block-layout-preview-container"
239
+ }, loadingPreview ? React.createElement("div", {
240
+ className: "so-panels-spinner-container"
241
+ }, React.createElement("span", null, React.createElement(Spinner, null))) : React.createElement("div", {
242
+ className: "so-panels-raw-html-container",
243
+ ref: this.previewContainer
244
+ }, React.createElement(RawHTML, null, this.state.previewHtml))));
245
+ }
246
+ }
247
+ }]);
248
+
249
+ return SiteOriginPanelsLayoutBlock;
250
+ }(Component);
251
+
252
+ registerBlockType('siteorigin-panels/layout-block', {
253
+ title: __('SiteOrigin Layout', 'siteorigin-panels'),
254
+ description: __("Build a layout using SiteOrigin's Page Builder.", 'siteorigin-panels'),
255
+ icon: function icon() {
256
+ return React.createElement("span", {
257
+ className: "siteorigin-panels-block-icon"
258
+ });
259
+ },
260
+ category: 'layout',
261
+ keywords: ['page builder', 'column,grid', 'panel'],
262
+ supports: {
263
+ html: false
264
+ },
265
+ attributes: {
266
+ panelsData: {
267
+ type: 'object'
268
+ }
269
+ },
270
+ edit: function edit(_ref) {
271
+ var attributes = _ref.attributes,
272
+ setAttributes = _ref.setAttributes,
273
+ toggleSelection = _ref.toggleSelection;
274
+
275
+ var onLayoutBlockContentChange = function onLayoutBlockContentChange(newPanelsData) {
276
+ if (!_.isEmpty(newPanelsData.widgets)) {
277
+ // Send panelsData to server for sanitization.
278
+ jQuery.post(soPanelsBlockEditorAdmin.sanitizeUrl, {
279
+ action: 'so_panels_layout_block_sanitize',
280
+ panelsData: JSON.stringify(newPanelsData)
281
+ }, function (sanitizedPanelsData) {
282
+ if (sanitizedPanelsData !== '') {
283
+ setAttributes({
284
+ panelsData: sanitizedPanelsData
285
+ });
286
+ }
287
+ });
288
+ }
289
+ };
290
+
291
+ var disableSelection = function disableSelection() {
292
+ toggleSelection(false);
293
+ };
294
+
295
+ var enableSelection = function enableSelection() {
296
+ toggleSelection(true);
297
+ };
298
+
299
+ return React.createElement(SiteOriginPanelsLayoutBlock, {
300
+ panelsData: attributes.panelsData,
301
+ onContentChange: onLayoutBlockContentChange,
302
+ onRowOrWidgetMouseDown: disableSelection,
303
+ onRowOrWidgetMouseUp: enableSelection
304
+ });
305
+ },
306
+ save: function save() {
307
+ // Render in PHP
308
+ return null;
309
+ }
310
+ });
311
+
312
+ (function (jQuery) {
313
+ if (soPanelsBlockEditorAdmin.showAddButton) {
314
+ jQuery(function () {
315
+ setTimeout(function () {
316
+ var editorDispatch = wp.data.dispatch('core/editor');
317
+ var editorSelect = wp.data.select('core/editor');
318
+ var tmpl = jQuery('#siteorigin-panels-add-layout-block-button').html();
319
+ var $addButton = jQuery(tmpl).insertAfter('.editor-writing-flow > div:first');
320
+ $addButton.on('click', function () {
321
+ var layoutBlock = wp.blocks.createBlock('siteorigin-panels/layout-block', {});
322
+ var isEmpty = editorSelect.isEditedPostEmpty();
323
+
324
+ if (isEmpty) {
325
+ var blocks = editorSelect.getBlocks();
326
+
327
+ if (blocks.length) {
328
+ editorDispatch.replaceBlock(blocks[0].clientId, layoutBlock);
329
+ } else {
330
+ editorDispatch.insertBlock(layoutBlock);
331
+ }
332
+ } else {
333
+ editorDispatch.insertBlock(layoutBlock);
334
+ }
335
+ });
336
+
337
+ var hideButtonIfBlocks = function hideButtonIfBlocks() {
338
+ var isEmpty = wp.data.select('core/editor').isEditedPostEmpty();
339
+
340
+ if (isEmpty) {
341
+ $addButton.show();
342
+ } else {
343
+ $addButton.hide();
344
+ }
345
+ };
346
+
347
+ wp.data.subscribe(hideButtonIfBlocks);
348
+ hideButtonIfBlocks();
349
+ }, 100);
350
+ });
351
+ }
352
  })(jQuery);
compat/js/siteorigin-panels-layout-block.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}function _possibleConstructorReturn(e,t){return!t||"object"!==_typeof(t)&&"function"!=typeof t?_assertThisInitialized(e):t}function _assertThisInitialized(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function _getPrototypeOf(e){return(_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&_setPrototypeOf(e,t)}function _setPrototypeOf(e,t){return(_setPrototypeOf=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var _lodash=lodash,isEqual=_lodash.isEqual,debounce=_lodash.debounce,isEmpty=_lodash.isEmpty,isFunction=_lodash.isFunction,registerBlockType=wp.blocks.registerBlockType,_wp$element=wp.element,Component=_wp$element.Component,Fragment=_wp$element.Fragment,RawHTML=_wp$element.RawHTML,createRef=_wp$element.createRef,BlockControls=wp.editor.BlockControls,_wp$components=wp.components,Toolbar=_wp$components.Toolbar,IconButton=_wp$components.IconButton,Spinner=_wp$components.Spinner,__=wp.i18n.__,_window=window,soPanelsBlockEditorAdmin=_window.soPanelsBlockEditorAdmin,SiteOriginPanelsLayoutBlock=function(e){function i(e){var t;_classCallCheck(this,i),t=_possibleConstructorReturn(this,_getPrototypeOf(i).call(this,e));var n="edit"===soPanelsBlockEditorAdmin.defaultMode||isEmpty(e.panelsData);return t.state={editing:n,loadingPreview:!n,previewHtml:""},t.panelsContainer=createRef(),t.previewContainer=createRef(),t.panelsInitialized=!1,t.previewInitialized=!1,t}return _inherits(i,Component),_createClass(i,[{key:"componentDidMount",value:function(){this.isStillMounted=!0,this.state.editing?this.setupPanels():this.state.editing||this.previewInitialized||(this.fetchPreview(this.props),this.fetchPreview=debounce(this.fetchPreview,500))}},{key:"componentWillUnmount",value:function(){this.isStillMounted=!1,this.builderView&&this.builderView.off("content_change")}},{key:"componentDidUpdate",value:function(e){this.state.editing&&!this.panelsInitialized?this.setupPanels():this.state.loadingPreview?this.fetchPreview(this.props):!this.previewInitialized&&this.previewContainer.current&&(jQuery(document).trigger("panels_setup_preview"),this.previewInitialized=!0)}},{key:"setupPanels",value:function(){var t=this,e=jQuery(this.panelsContainer.current),n=new panels.model.builder;this.builderView=new panels.view.builder({model:n,config:{editorType:"standalone"}});var i=JSON.parse(JSON.stringify(jQuery.extend({},this.props.panelsData))),o=function(){isFunction(t.props.onRowOrWidgetMouseDown)&&t.props.onRowOrWidgetMouseDown();jQuery(document).on("mouseup",function e(){jQuery(document).off("mouseup",e),isFunction(t.props.onRowOrWidgetMouseUp)&&t.props.onRowOrWidgetMouseUp()})};this.builderView.on("row_added",function(){t.builderView.$(".so-row-move").off("mousedown",o),t.builderView.$(".so-row-move").on("mousedown",o),t.builderView.$(".so-widget").off("mousedown",o),t.builderView.$(".so-widget").on("mousedown",o)}),this.builderView.on("widget_added",function(){t.builderView.$(".so-widget").off("mousedown",o),t.builderView.$(".so-widget").on("mousedown",o)}),this.builderView.render().attach({container:e}).setData(i),this.builderView.trigger("builder_resize"),this.builderView.on("content_change",function(){var e=t.builderView.getData();t.panelsDataChanged=!isEqual(i,e),t.panelsDataChanged&&(t.props.onContentChange&&isFunction(t.props.onContentChange)&&t.props.onContentChange(e),t.setState({loadingPreview:!0,previewHtml:""}))}),jQuery(document).trigger("panels_setup",this.builderView),this.panelsInitialized=!0}},{key:"fetchPreview",value:function(e){var t=this;if(this.isStillMounted){this.previewInitialized=!1;var n=this.currentFetchRequest=jQuery.post({url:soPanelsBlockEditorAdmin.previewUrl,data:{action:"so_panels_layout_block_preview",panelsData:JSON.stringify(e.panelsData)}}).then(function(e){t.isStillMounted&&n===t.currentFetchRequest&&e&&t.setState({previewHtml:e,loadingPreview:!1})});return n}}},{key:"render",value:function(){var e=this,t=this.props.panelsData;if(this.state.editing)return React.createElement(Fragment,null,React.createElement(BlockControls,null,React.createElement(Toolbar,null,React.createElement(IconButton,{icon:"visibility",className:"components-icon-button components-toolbar__control",label:__("Preview layout.","siteorigin-panels"),onClick:function(){t&&e.setState({editing:!1})}}))),React.createElement("div",{key:"layout-block",className:"siteorigin-panels-layout-block-container",ref:this.panelsContainer}));var n=this.state.loadingPreview;return React.createElement(Fragment,null,React.createElement(BlockControls,null,React.createElement(Toolbar,null,React.createElement(IconButton,{icon:"edit",className:"components-icon-button components-toolbar__control",label:__("Edit layout.","siteorigin-panels"),onClick:function(){e.panelsInitialized=!1,e.setState({editing:!0})}}))),React.createElement("div",{key:"preview",className:"so-panels-block-layout-preview-container"},n?React.createElement("div",{className:"so-panels-spinner-container"},React.createElement("span",null,React.createElement(Spinner,null))):React.createElement("div",{className:"so-panels-raw-html-container",ref:this.previewContainer},React.createElement(RawHTML,null,this.state.previewHtml))))}}]),i}();registerBlockType("siteorigin-panels/layout-block",{title:__("SiteOrigin Layout","siteorigin-panels"),description:__("Build a layout using SiteOrigin's Page Builder.","siteorigin-panels"),icon:function(){return React.createElement("span",{className:"siteorigin-panels-block-icon"})},category:"layout",keywords:["page builder","column,grid","panel"],supports:{html:!1},attributes:{panelsData:{type:"object"}},edit:function(e){var t=e.attributes,n=e.setAttributes,i=e.toggleSelection;return React.createElement(SiteOriginPanelsLayoutBlock,{panelsData:t.panelsData,onContentChange:function(e){_.isEmpty(e.widgets)||jQuery.post(soPanelsBlockEditorAdmin.sanitizeUrl,{action:"so_panels_layout_block_sanitize",panelsData:JSON.stringify(e)},function(e){""!==e&&n({panelsData:e})})},onRowOrWidgetMouseDown:function(){i(!1)},onRowOrWidgetMouseUp:function(){i(!0)}})},save:function(){return null}}),function(r){soPanelsBlockEditorAdmin.showAddButton&&r(function(){setTimeout(function(){var n=wp.data.dispatch("core/editor"),i=wp.data.select("core/editor"),e=r("#siteorigin-panels-add-layout-block-button").html(),t=r(e).insertAfter(".editor-writing-flow > div:first");t.on("click",function(){var e=wp.blocks.createBlock("siteorigin-panels/layout-block",{});if(i.isEditedPostEmpty()){var t=i.getBlocks();t.length?n.replaceBlock(t[0].clientId,e):n.insertBlock(e)}else n.insertBlock(e)});var o=function(){wp.data.select("core/editor").isEditedPostEmpty()?t.show():t.hide()};wp.data.subscribe(o),o()},100)})}(jQuery);
1
+ "use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}function _possibleConstructorReturn(e,t){return!t||"object"!==_typeof(t)&&"function"!=typeof t?_assertThisInitialized(e):t}function _assertThisInitialized(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function _getPrototypeOf(e){return(_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&_setPrototypeOf(e,t)}function _setPrototypeOf(e,t){return(_setPrototypeOf=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var _lodash=lodash,isEqual=_lodash.isEqual,debounce=_lodash.debounce,isEmpty=_lodash.isEmpty,isFunction=_lodash.isFunction,registerBlockType=wp.blocks.registerBlockType,_wp$element=wp.element,Component=_wp$element.Component,Fragment=_wp$element.Fragment,RawHTML=_wp$element.RawHTML,createRef=_wp$element.createRef,BlockControls=wp.editor.BlockControls,_wp$components=wp.components,Toolbar=_wp$components.Toolbar,IconButton=_wp$components.IconButton,Spinner=_wp$components.Spinner,__=wp.i18n.__,_window=window,soPanelsBlockEditorAdmin=_window.soPanelsBlockEditorAdmin,SiteOriginPanelsLayoutBlock=function(){function i(e){var t;_classCallCheck(this,i),t=_possibleConstructorReturn(this,_getPrototypeOf(i).call(this,e));var n="edit"===soPanelsBlockEditorAdmin.defaultMode||isEmpty(e.panelsData);return t.state={editing:n,loadingPreview:!n,previewHtml:""},t.panelsContainer=createRef(),t.previewContainer=createRef(),t.panelsInitialized=!1,t.previewInitialized=!1,t}return _inherits(i,Component),_createClass(i,[{key:"componentDidMount",value:function(){this.isStillMounted=!0,this.state.editing?this.setupPanels():this.state.editing||this.previewInitialized||(this.fetchPreview(this.props),this.fetchPreview=debounce(this.fetchPreview,500))}},{key:"componentWillUnmount",value:function(){this.isStillMounted=!1,this.builderView&&this.builderView.off("content_change")}},{key:"componentDidUpdate",value:function(e){this.state.editing&&!this.panelsInitialized?this.setupPanels():this.state.loadingPreview?this.fetchPreview(this.props):!this.previewInitialized&&this.previewContainer.current&&(jQuery(document).trigger("panels_setup_preview"),this.previewInitialized=!0)}},{key:"setupPanels",value:function(){var t=this,e=jQuery(this.panelsContainer.current),n=new panels.model.builder;this.builderView=new panels.view.builder({model:n,config:{editorType:"standalone"}});function i(){isFunction(t.props.onRowOrWidgetMouseDown)&&t.props.onRowOrWidgetMouseDown(),jQuery(document).on("mouseup",function e(){jQuery(document).off("mouseup",e),isFunction(t.props.onRowOrWidgetMouseUp)&&t.props.onRowOrWidgetMouseUp()})}var o=JSON.parse(JSON.stringify(jQuery.extend({},this.props.panelsData)));this.builderView.on("row_added",function(){t.builderView.$(".so-row-move").off("mousedown",i),t.builderView.$(".so-row-move").on("mousedown",i),t.builderView.$(".so-widget").off("mousedown",i),t.builderView.$(".so-widget").on("mousedown",i)}),this.builderView.on("widget_added",function(){t.builderView.$(".so-widget").off("mousedown",i),t.builderView.$(".so-widget").on("mousedown",i)}),this.builderView.render().attach({container:e}).setData(o),this.builderView.trigger("builder_resize"),this.builderView.on("content_change",function(){var e=t.builderView.getData();t.panelsDataChanged=!isEqual(o,e),t.panelsDataChanged&&(t.props.onContentChange&&isFunction(t.props.onContentChange)&&t.props.onContentChange(e),t.setState({loadingPreview:!0,previewHtml:""}))}),jQuery(document).trigger("panels_setup",this.builderView),this.panelsInitialized=!0}},{key:"fetchPreview",value:function(e){var t=this;if(this.isStillMounted){this.previewInitialized=!1;var n=this.currentFetchRequest=jQuery.post({url:soPanelsBlockEditorAdmin.previewUrl,data:{action:"so_panels_layout_block_preview",panelsData:JSON.stringify(e.panelsData)}}).then(function(e){t.isStillMounted&&n===t.currentFetchRequest&&e&&t.setState({previewHtml:e,loadingPreview:!1})});return n}}},{key:"render",value:function(){var e=this,t=this.props.panelsData;if(this.state.editing)return React.createElement(Fragment,null,React.createElement(BlockControls,null,React.createElement(Toolbar,null,React.createElement(IconButton,{icon:"visibility",className:"components-icon-button components-toolbar__control",label:__("Preview layout.","siteorigin-panels"),onClick:function(){t&&e.setState({editing:!1})}}))),React.createElement("div",{key:"layout-block",className:"siteorigin-panels-layout-block-container",ref:this.panelsContainer}));var n=this.state.loadingPreview;return React.createElement(Fragment,null,React.createElement(BlockControls,null,React.createElement(Toolbar,null,React.createElement(IconButton,{icon:"edit",className:"components-icon-button components-toolbar__control",label:__("Edit layout.","siteorigin-panels"),onClick:function(){e.panelsInitialized=!1,e.setState({editing:!0})}}))),React.createElement("div",{key:"preview",className:"so-panels-block-layout-preview-container"},n?React.createElement("div",{className:"so-panels-spinner-container"},React.createElement("span",null,React.createElement(Spinner,null))):React.createElement("div",{className:"so-panels-raw-html-container",ref:this.previewContainer},React.createElement(RawHTML,null,this.state.previewHtml))))}}]),i}();registerBlockType("siteorigin-panels/layout-block",{title:__("SiteOrigin Layout","siteorigin-panels"),description:__("Build a layout using SiteOrigin's Page Builder.","siteorigin-panels"),icon:function(){return React.createElement("span",{className:"siteorigin-panels-block-icon"})},category:"layout",keywords:["page builder","column,grid","panel"],supports:{html:!1},attributes:{panelsData:{type:"object"}},edit:function(e){var t=e.attributes,n=e.setAttributes,i=e.toggleSelection;return React.createElement(SiteOriginPanelsLayoutBlock,{panelsData:t.panelsData,onContentChange:function(e){_.isEmpty(e.widgets)||jQuery.post(soPanelsBlockEditorAdmin.sanitizeUrl,{action:"so_panels_layout_block_sanitize",panelsData:JSON.stringify(e)},function(e){""!==e&&n({panelsData:e})})},onRowOrWidgetMouseDown:function(){i(!1)},onRowOrWidgetMouseUp:function(){i(!0)}})},save:function(){return null}}),function(r){soPanelsBlockEditorAdmin.showAddButton&&r(function(){setTimeout(function(){var n=wp.data.dispatch("core/editor"),i=wp.data.select("core/editor"),e=r("#siteorigin-panels-add-layout-block-button").html(),t=r(e).insertAfter(".editor-writing-flow > div:first");t.on("click",function(){var e=wp.blocks.createBlock("siteorigin-panels/layout-block",{});if(i.isEditedPostEmpty()){var t=i.getBlocks();t.length?n.replaceBlock(t[0].clientId,e):n.insertBlock(e)}else n.insertBlock(e)});function o(){wp.data.select("core/editor").isEditedPostEmpty()?t.show():t.hide()}wp.data.subscribe(o),o()},100)})}(jQuery);
compat/layout-block.php CHANGED
@@ -1,114 +1,114 @@
1
- <?php
2
-
3
- class SiteOrigin_Panels_Compat_Layout_Block {
4
-
5
- const BLOCK_NAME = 'siteorigin-panels/layout-block';
6
-
7
- /**
8
- * Get the singleton instance
9
- *
10
- * @return SiteOrigin_Panels_Compat_Layout_Block
11
- */
12
- public static function single() {
13
- static $single;
14
-
15
- return empty( $single ) ? $single = new self() : $single;
16
- }
17
-
18
- public function __construct() {
19
- add_action( 'init', array( $this, 'register_layout_block' ) );
20
- // This action is slightly later than `enqueue_block_editor_assets`,
21
- // which we need to use to ensure our templates are loaded at the right time.
22
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_layout_block_editor_assets' ) );
23
- }
24
-
25
- public function register_layout_block() {
26
- register_block_type( self::BLOCK_NAME, array(
27
- 'render_callback' => array( $this, 'render_layout_block' ),
28
- ) );
29
- }
30
-
31
- public function enqueue_layout_block_editor_assets() {
32
- if ( SiteOrigin_Panels_Admin::is_block_editor() ) {
33
- $panels_admin = SiteOrigin_Panels_Admin::single();
34
- $panels_admin->enqueue_admin_scripts();
35
- $panels_admin->enqueue_admin_styles();
36
- $panels_admin->js_templates();
37
-
38
- wp_enqueue_script(
39
- 'siteorigin-panels-layout-block',
40
- plugins_url( 'js/siteorigin-panels-layout-block' . SITEORIGIN_PANELS_JS_SUFFIX . '.js', __FILE__ ),
41
- array(
42
- 'wp-editor',
43
- 'wp-blocks',
44
- 'wp-i18n',
45
- 'wp-element',
46
- 'wp-components',
47
- 'wp-compose',
48
- 'so-panels-admin'
49
- ),
50
- SITEORIGIN_PANELS_VERSION
51
- );
52
-
53
- $current_screen = get_current_screen();
54
- $is_panels_post_type = in_array( $current_screen->id, siteorigin_panels_setting( 'post-types' ) );
55
- wp_localize_script(
56
- 'siteorigin-panels-layout-block',
57
- 'soPanelsBlockEditorAdmin',
58
- array(
59
- 'sanitizeUrl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'layout-block-sanitize', '_panelsnonce' ),
60
- 'previewUrl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'layout-block-preview', '_panelsnonce' ),
61
- 'defaultMode' => siteorigin_panels_setting( 'layout-block-default-mode' ),
62
- 'showAddButton' => $is_panels_post_type,
63
- )
64
- );
65
- // This is only available in WP5.
66
- if ( function_exists( 'wp_set_script_translations' ) ) {
67
- wp_set_script_translations( 'siteorigin-panels-layout-block', 'siteorigin-panels' );
68
- }
69
- SiteOrigin_Panels_Styles::register_scripts();
70
- wp_enqueue_script( 'siteorigin-panels-front-styles' );
71
-
72
- // Enqueue front end scripts for our widgets bundle.
73
- if ( class_exists( 'SiteOrigin_Widgets_Bundle' ) ) {
74
- $sowb = SiteOrigin_Widgets_Bundle::single();
75
- $sowb->register_general_scripts();
76
- if ( method_exists( $sowb, 'enqueue_registered_widgets_scripts' ) ) {
77
- $sowb->enqueue_registered_widgets_scripts( true, false );
78
- }
79
- }
80
- }
81
- }
82
-
83
- public function render_layout_block( $attributes ) {
84
-
85
- if ( empty( $attributes['panelsData'] ) ) {
86
- return '<div>'.
87
- __( "You need to add a widget, row, or prebuilt layout before you'll see anything here. :)", 'siteorigin-panels' ) .
88
- '</div>';
89
- }
90
- $panels_data = $attributes['panelsData'];
91
- $panels_data = $this->sanitize_panels_data( $panels_data );
92
- $builder_id = isset( $attributes['builder_id'] ) ? $attributes['builder_id'] : uniqid( 'gb' . get_the_ID() . '-' );
93
-
94
- // Support for custom CSS classes
95
- $add_custom_class_name = function( $class_names ) use ($attributes) {
96
- if ( ! empty( $attributes['className'] ) ) {
97
- $class_names[] = $attributes['className'];
98
- }
99
- return $class_names;
100
- };
101
- add_filter( 'siteorigin_panels_layout_classes', $add_custom_class_name );
102
- $rendered_layout = SiteOrigin_Panels::renderer()->render( $builder_id, true, $panels_data );
103
- remove_filter( 'siteorigin_panels_layout_classes', $add_custom_class_name );
104
- return $rendered_layout;
105
- }
106
-
107
- private function sanitize_panels_data( $panels_data ) {
108
- // We force calling widgets' update functions here, but a better solution is to ensure these are called when
109
- // the block is saved, but there is currently no simple method to do so.
110
- $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], false, true );
111
- $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
112
- return $panels_data;
113
- }
114
- }
1
+ <?php
2
+
3
+ class SiteOrigin_Panels_Compat_Layout_Block {
4
+
5
+ const BLOCK_NAME = 'siteorigin-panels/layout-block';
6
+
7
+ /**
8
+ * Get the singleton instance
9
+ *
10
+ * @return SiteOrigin_Panels_Compat_Layout_Block
11
+ */
12
+ public static function single() {
13
+ static $single;
14
+
15
+ return empty( $single ) ? $single = new self() : $single;
16
+ }
17
+
18
+ public function __construct() {
19
+ add_action( 'init', array( $this, 'register_layout_block' ) );
20
+ // This action is slightly later than `enqueue_block_editor_assets`,
21
+ // which we need to use to ensure our templates are loaded at the right time.
22
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_layout_block_editor_assets' ) );
23
+ }
24
+
25
+ public function register_layout_block() {
26
+ register_block_type( self::BLOCK_NAME, array(
27
+ 'render_callback' => array( $this, 'render_layout_block' ),
28
+ ) );
29
+ }
30
+
31
+ public function enqueue_layout_block_editor_assets() {
32
+ if ( SiteOrigin_Panels_Admin::is_block_editor() ) {
33
+ $panels_admin = SiteOrigin_Panels_Admin::single();
34
+ $panels_admin->enqueue_admin_scripts();
35
+ $panels_admin->enqueue_admin_styles();
36
+ $panels_admin->js_templates();
37
+
38
+ wp_enqueue_script(
39
+ 'siteorigin-panels-layout-block',
40
+ plugins_url( 'js/siteorigin-panels-layout-block' . SITEORIGIN_PANELS_JS_SUFFIX . '.js', __FILE__ ),
41
+ array(
42
+ 'wp-editor',
43
+ 'wp-blocks',
44
+ 'wp-i18n',
45
+ 'wp-element',
46
+ 'wp-components',
47
+ 'wp-compose',
48
+ 'so-panels-admin'
49
+ ),
50
+ SITEORIGIN_PANELS_VERSION
51
+ );
52
+
53
+ $current_screen = get_current_screen();
54
+ $is_panels_post_type = in_array( $current_screen->id, siteorigin_panels_setting( 'post-types' ) );
55
+ wp_localize_script(
56
+ 'siteorigin-panels-layout-block',
57
+ 'soPanelsBlockEditorAdmin',
58
+ array(
59
+ 'sanitizeUrl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'layout-block-sanitize', '_panelsnonce' ),
60
+ 'previewUrl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'layout-block-preview', '_panelsnonce' ),
61
+ 'defaultMode' => siteorigin_panels_setting( 'layout-block-default-mode' ),
62
+ 'showAddButton' => apply_filters( 'siteorigin_layout_block_show_add_button', $is_panels_post_type ),
63
+ )
64
+ );
65
+ // This is only available in WP5.
66
+ if ( function_exists( 'wp_set_script_translations' ) ) {
67
+ wp_set_script_translations( 'siteorigin-panels-layout-block', 'siteorigin-panels' );
68
+ }
69
+ SiteOrigin_Panels_Styles::register_scripts();
70
+ wp_enqueue_script( 'siteorigin-panels-front-styles' );
71
+
72
+ // Enqueue front end scripts for our widgets bundle.
73
+ if ( class_exists( 'SiteOrigin_Widgets_Bundle' ) ) {
74
+ $sowb = SiteOrigin_Widgets_Bundle::single();
75
+ $sowb->register_general_scripts();
76
+ if ( method_exists( $sowb, 'enqueue_registered_widgets_scripts' ) ) {
77
+ $sowb->enqueue_registered_widgets_scripts( true, false );
78
+ }
79
+ }
80
+ }
81
+ }
82
+
83
+ public function render_layout_block( $attributes ) {
84
+
85
+ if ( empty( $attributes['panelsData'] ) ) {
86
+ return '<div>'.
87
+ __( "You need to add a widget, row, or prebuilt layout before you'll see anything here. :)", 'siteorigin-panels' ) .
88
+ '</div>';
89
+ }
90
+ $panels_data = $attributes['panelsData'];
91
+ $panels_data = $this->sanitize_panels_data( $panels_data );
92
+ $builder_id = isset( $attributes['builder_id'] ) ? $attributes['builder_id'] : uniqid( 'gb' . get_the_ID() . '-' );
93
+
94
+ // Support for custom CSS classes
95
+ $add_custom_class_name = function( $class_names ) use ($attributes) {
96
+ if ( ! empty( $attributes['className'] ) ) {
97
+ $class_names[] = $attributes['className'];
98
+ }
99
+ return $class_names;
100
+ };
101
+ add_filter( 'siteorigin_panels_layout_classes', $add_custom_class_name );
102
+ $rendered_layout = SiteOrigin_Panels::renderer()->render( $builder_id, true, $panels_data );
103
+ remove_filter( 'siteorigin_panels_layout_classes', $add_custom_class_name );
104
+ return $rendered_layout;
105
+ }
106
+
107
+ private function sanitize_panels_data( $panels_data ) {
108
+ // We force calling widgets' update functions here, but a better solution is to ensure these are called when
109
+ // the block is saved, but there is currently no simple method to do so.
110
+ $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], false, true );
111
+ $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
112
+ return $panels_data;
113
+ }
114
+ }
compat/pb-icon.svg DELETED
@@ -1 +0,0 @@
1
- <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 703.29 745.09"><defs><style>.cls-1{opacity:0.5;}.cls-2{opacity:0.2;}</style></defs><title>pb-icon</title><path d="M731.52,232.52,397,430.73a17.11,17.11,0,0,1-17.45,0L45,232.52a17.12,17.12,0,0,1,0-29.46L379.54,4.85a17.11,17.11,0,0,1,17.45,0L731.52,203.06A17.12,17.12,0,0,1,731.52,232.52Z" transform="translate(-36.62 -2.46)"/><path class="cls-1" d="M731.52,399.94,397,598.15a17.11,17.11,0,0,1-17.45,0L45,399.94a17.12,17.12,0,0,1,0-29.46L379.54,172.27a17.11,17.11,0,0,1,17.45,0L731.52,370.48A17.12,17.12,0,0,1,731.52,399.94Z" transform="translate(-36.62 -2.46)"/><path class="cls-2" d="M731.52,546.94,397,745.15a17.11,17.11,0,0,1-17.45,0L45,546.94a17.12,17.12,0,0,1,0-29.46L379.54,319.27a17.11,17.11,0,0,1,17.45,0L731.52,517.48A17.12,17.12,0,0,1,731.52,546.94Z" transform="translate(-36.62 -2.46)"/></svg>
 
compat/pb-icon_white.svg DELETED
@@ -1 +0,0 @@
1
- <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 703.29 745.09"><defs><style>.cls-1{opacity:0.5;}.cls-2{opacity:0.2;}</style></defs><title>pb-icon</title><path fill="white" d="M731.52,232.52,397,430.73a17.11,17.11,0,0,1-17.45,0L45,232.52a17.12,17.12,0,0,1,0-29.46L379.54,4.85a17.11,17.11,0,0,1,17.45,0L731.52,203.06A17.12,17.12,0,0,1,731.52,232.52Z" transform="translate(-36.62 -2.46)"/><path class="cls-1" fill="white" d="M731.52,399.94,397,598.15a17.11,17.11,0,0,1-17.45,0L45,399.94a17.12,17.12,0,0,1,0-29.46L379.54,172.27a17.11,17.11,0,0,1,17.45,0L731.52,370.48A17.12,17.12,0,0,1,731.52,399.94Z" transform="translate(-36.62 -2.46)"/><path fill="white" class="cls-2" d="M731.52,546.94,397,745.15a17.11,17.11,0,0,1-17.45,0L45,546.94a17.12,17.12,0,0,1,0-29.46L379.54,319.27a17.11,17.11,0,0,1,17.45,0L731.52,517.48A17.12,17.12,0,0,1,731.52,546.94Z" transform="translate(-36.62 -2.46)"/></svg>
 
css/front.css DELETED
@@ -1,47 +0,0 @@
1
- .panel-grid.panel-no-style,
2
- .panel-grid.panel-has-style > .panel-row-style {
3
- display: -webkit-flex;
4
- display: flex;
5
- -ms-flex-wrap: wrap;
6
- -webkit-flex-wrap: wrap;
7
- flex-wrap: nowrap;
8
- -ms-justify-content: space-between;
9
- -webkit-justify-content: space-between;
10
- justify-content: space-between;
11
- }
12
- .panel-grid-cell {
13
- -ms-box-sizing: border-box;
14
- -moz-box-sizing: border-box;
15
- -webkit-box-sizing: border-box;
16
- box-sizing: border-box;
17
- }
18
- .panel-grid-cell .panel-cell-style {
19
- height: 100%;
20
- }
21
- .panel-grid-cell .so-panel {
22
- zoom: 1;
23
- }
24
- .panel-grid-cell .so-panel:before {
25
- content: '';
26
- display: block;
27
- }
28
- .panel-grid-cell .so-panel:after {
29
- content: '';
30
- display: table;
31
- clear: both;
32
- }
33
- .panel-grid-cell .panel-last-child {
34
- margin-bottom: 0;
35
- }
36
- .panel-grid-cell .widget-title {
37
- margin-top: 0;
38
- }
39
- body.siteorigin-panels-before-js {
40
- overflow-x: hidden;
41
- }
42
- body.siteorigin-panels-before-js .siteorigin-panels-stretch {
43
- margin-right: -1000px !important;
44
- margin-left: -1000px !important;
45
- padding-right: 1000px !important;
46
- padding-left: 1000px !important;
47
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
css/front.min.css DELETED
@@ -1 +0,0 @@
1
- .panel-grid.panel-has-style>.panel-row-style,.panel-grid.panel-no-style{display:flex;-ms-flex-wrap:wrap;flex-wrap:nowrap;-ms-justify-content:space-between;justify-content:space-between}.panel-grid-cell{-ms-box-sizing:border-box;box-sizing:border-box}.panel-grid-cell .panel-cell-style{height:100%}.panel-grid-cell .so-panel{zoom:1}.panel-grid-cell .so-panel:before{content:"";display:block}.panel-grid-cell .so-panel:after{content:"";display:table;clear:both}.panel-grid-cell .panel-last-child{margin-bottom:0}.panel-grid-cell .widget-title{margin-top:0}body.siteorigin-panels-before-js{overflow-x:hidden}body.siteorigin-panels-before-js .siteorigin-panels-stretch{margin-right:-1000px!important;margin-left:-1000px!important;padding-right:1000px!important;padding-left:1000px!important}
 
css/icons/readme.txt DELETED
@@ -1,5 +0,0 @@
1
- Icons are a subset of FontAwesome
2
- Font Awesome by Dave Gandy - http://fontawesome.io
3
-
4
- License: SIL OFL 1.1
5
- URL: http://scripts.sil.org/OFL
 
 
 
 
 
css/images/pb-icon_white.svg CHANGED
@@ -1 +1 @@
1
- <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 703.29 745.09"><defs><style>.cls-1{opacity:0.5;}.cls-2{opacity:0.2;}</style></defs><title>pb-icon</title><path fill="white" d="M731.52,232.52,397,430.73a17.11,17.11,0,0,1-17.45,0L45,232.52a17.12,17.12,0,0,1,0-29.46L379.54,4.85a17.11,17.11,0,0,1,17.45,0L731.52,203.06A17.12,17.12,0,0,1,731.52,232.52Z" transform="translate(-36.62 -2.46)"/><path class="cls-1" fill="white" d="M731.52,399.94,397,598.15a17.11,17.11,0,0,1-17.45,0L45,399.94a17.12,17.12,0,0,1,0-29.46L379.54,172.27a17.11,17.11,0,0,1,17.45,0L731.52,370.48A17.12,17.12,0,0,1,731.52,399.94Z" transform="translate(-36.62 -2.46)"/><path fill="white" class="cls-2" d="M731.52,546.94,397,745.15a17.11,17.11,0,0,1-17.45,0L45,546.94a17.12,17.12,0,0,1,0-29.46L379.54,319.27a17.11,17.11,0,0,1,17.45,0L731.52,517.48A17.12,17.12,0,0,1,731.52,546.94Z" transform="translate(-36.62 -2.46)"/></svg>
1
+ <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 703.29 745.09"><defs><style>.cls-1{opacity:0.5;}.cls-2{opacity:0.2;}</style></defs><title>pb-icon</title><path fill="white" d="M731.52,232.52,397,430.73a17.11,17.11,0,0,1-17.45,0L45,232.52a17.12,17.12,0,0,1,0-29.46L379.54,4.85a17.11,17.11,0,0,1,17.45,0L731.52,203.06A17.12,17.12,0,0,1,731.52,232.52Z" transform="translate(-36.62 -2.46)"/><path class="cls-1" fill="white" d="M731.52,399.94,397,598.15a17.11,17.11,0,0,1-17.45,0L45,399.94a17.12,17.12,0,0,1,0-29.46L379.54,172.27a17.11,17.11,0,0,1,17.45,0L731.52,370.48A17.12,17.12,0,0,1,731.52,399.94Z" transform="translate(-36.62 -2.46)"/><path fill="white" class="cls-2" d="M731.52,546.94,397,745.15a17.11,17.11,0,0,1-17.45,0L45,546.94a17.12,17.12,0,0,1,0-29.46L379.54,319.27a17.11,17.11,0,0,1,17.45,0L731.52,517.48A17.12,17.12,0,0,1,731.52,546.94Z" transform="translate(-36.62 -2.46)"/></svg>
css/mixins.less DELETED
@@ -1,173 +0,0 @@
1
- .gradient(@color: #F5F5F5, @start: #EEE, @stop: #FFF) {
2
- background: @color;
3
- background: -webkit-gradient(linear, left bottom, left top, color-stop(0, @start), color-stop(1, @stop));
4
- background: -ms-linear-gradient(bottom,@start,@stop);
5
- background: -moz-linear-gradient(center bottom,@start 0%,@stop 100%);
6
- background: -o-linear-gradient(@stop,@start);
7
- filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)", @stop, @start));
8
- }
9
-
10
- .bw-gradient(@color: #F5F5F5, @start: 0, @stop: 255) {
11
- background: @color;
12
- background: -webkit-gradient(linear, left bottom, left top, color-stop(0, rgb(@start,@start,@start)), color-stop(1, rgb(@stop,@stop,@stop)));
13
- background: -ms-linear-gradient(bottom, rgb(@start,@start,@start) 0%, rgb(@stop,@stop,@stop) 100%);
14
- background: -moz-linear-gradient(center bottom, rgb(@start,@start,@start) 0%, rgb(@stop,@stop,@stop) 100%);
15
- background: -o-linear-gradient(rgb(@stop,@stop,@stop), rgb(@start,@start,@start));
16
- background: linear-gradient(rgb(@stop,@stop,@stop), rgb(@start,@start,@start));
17
-
18
- filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",rgb(@stop,@stop,@stop), rgb(@start,@start,@start)));
19
- }
20
-
21
- .linear-gradient(@color, @gradient) {
22
- background: @color;
23
- background: -moz-linear-gradient(@gradient);
24
- background: -webkit-linear-gradient(@gradient);
25
- background: -o-linear-gradient(@gradient);
26
- background: -ms-linear-gradient(@gradient);
27
- background: linear-gradient(@gradient);
28
- }
29
-
30
- .bordered(@top-color: #EEE, @right-color: #EEE, @bottom-color: #EEE, @left-color: #EEE) {
31
- border-top: solid 1px @top-color;
32
- border-left: solid 1px @left-color;
33
- border-right: solid 1px @right-color;
34
- border-bottom: solid 1px @bottom-color;
35
- }
36
-
37
- .drop-shadow(@x-axis: 0, @y-axis: 1px, @blur: 2px, @alpha: 0.1) {
38
- -webkit-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
39
- -moz-box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
40
- box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha);
41
- }
42
-
43
- .box-shadow(@shadow) {
44
- -webkit-box-shadow: @shadow;
45
- -moz-box-shadow: @shadow;
46
- box-shadow: @shadow;
47
- }
48
-
49
- .rounded(@radius: 2px) {
50
- -webkit-border-radius: @radius;
51
- -moz-border-radius: @radius;
52
- border-radius: @radius;
53
- }
54
-
55
- .border-radius(@topright: 0, @bottomright: 0, @bottomleft: 0, @topleft: 0) {
56
- -webkit-border-top-right-radius: @topright;
57
- -webkit-border-bottom-right-radius: @bottomright;
58
- -webkit-border-bottom-left-radius: @bottomleft;
59
- -webkit-border-top-left-radius: @topleft;
60
- -moz-border-radius-topright: @topright;
61
- -moz-border-radius-bottomright: @bottomright;
62
- -moz-border-radius-bottomleft: @bottomleft;
63
- -moz-border-radius-topleft: @topleft;
64
- border-top-right-radius: @topright;
65
- border-bottom-right-radius: @bottomright;
66
- border-bottom-left-radius: @bottomleft;
67
- border-top-left-radius: @topleft;
68
- .background-clip(padding-box);
69
- }
70
-
71
- .opacity(@opacity: 0.5) {
72
- -moz-opacity: @opacity;
73
- -khtml-opacity: @opacity;
74
- -webkit-opacity: @opacity;
75
- opacity: @opacity;
76
- @opperc: @opacity * 100;
77
- -ms-filter: ~"progid:DXImageTransform.Microsoft.Alpha(opacity=@{opperc})";
78
- filter: ~"alpha(opacity=@{opperc})";
79
- }
80
-
81
- .transition-duration(@duration: 0.2s) {
82
- -moz-transition-duration: @duration;
83
- -webkit-transition-duration: @duration;
84
- -o-transition-duration: @duration;
85
- transition-duration: @duration;
86
- }
87
-
88
- .transform(...) {
89
- -webkit-transform: @arguments;
90
- -moz-transform: @arguments;
91
- -o-transform: @arguments;
92
- -ms-transform: @arguments;
93
- transform: @arguments;
94
- }
95
-
96
- .rotation(@deg:5deg) {
97
- .transform(rotate(@deg));
98
- }
99
-
100
- .scale(@ratio:1.5) {
101
- .transform(scale(@ratio));
102
- }
103
-
104
- .transition(@duration:0.2s, @on: all, @ease:ease) {
105
- -webkit-transition: @on @duration @ease;
106
- -moz-transition: @on @duration @ease;
107
- -o-transition: @on @duration @ease;
108
- transition: @on @duration @ease;
109
- }
110
-
111
- .inner-shadow(@horizontal:0, @vertical:1px, @blur:2px, @alpha: 0.4) {
112
- -webkit-box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
113
- -moz-box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
114
- box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha);
115
- }
116
-
117
- .box-sizing(@sizing: border-box) {
118
- -ms-box-sizing: @sizing;
119
- -moz-box-sizing: @sizing;
120
- -webkit-box-sizing: @sizing;
121
- box-sizing: @sizing;
122
- }
123
-
124
- .user-select(@argument: none) {
125
- -webkit-user-select: @argument;
126
- -moz-user-select: @argument;
127
- -ms-user-select: @argument;
128
- user-select: @argument;
129
- }
130
-
131
- .columns(@colwidth: 250px, @colcount: 0, @colgap: 50px, @columnRuleColor: #EEE, @columnRuleStyle: solid, @columnRuleWidth: 1px) {
132
- -moz-column-width: @colwidth;
133
- -moz-column-count: @colcount;
134
- -moz-column-gap: @colgap;
135
- -moz-column-rule-color: @columnRuleColor;
136
- -moz-column-rule-style: @columnRuleStyle;
137
- -moz-column-rule-width: @columnRuleWidth;
138
- -webkit-column-width: @colwidth;
139
- -webkit-column-count: @colcount;
140
- -webkit-column-gap: @colgap;
141
- -webkit-column-rule-color: @columnRuleColor;
142
- -webkit-column-rule-style: @columnRuleStyle;
143
- -webkit-column-rule-width: @columnRuleWidth;
144
- column-width: @colwidth;
145
- column-count: @colcount;
146
- column-gap: @colgap;
147
- column-rule-color: @columnRuleColor;
148
- column-rule-style: @columnRuleStyle;
149
- column-rule-width: @columnRuleWidth;
150
- }
151
-
152
- .translate(@x:0, @y:0) {
153
- .transform(translate(@x, @y));
154
- }
155
-
156
- .background-clip(@argument: padding-box) {
157
- -moz-background-clip: @argument;
158
- -webkit-background-clip: @argument;
159
- background-clip: @argument;
160
- }
161
-
162
- .clearfix() {
163
- zoom: 1;
164
- &:before {
165
- content: '';
166
- display: block;
167
- }
168
- &:after {
169
- content: '';
170
- display: table;
171
- clear: both;
172
- }
173
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/admin-dashboard.php CHANGED
@@ -1,117 +1,117 @@
1
- <?php
2
-
3
- class SiteOrigin_Panels_Admin_Dashboard {
4
-
5
- function __construct() {
6
- add_action( 'wp_dashboard_setup', array( $this, 'register_dashboard_widgets' ), 15 );
7
- add_action( 'admin_print_styles', array( $this, 'enqueue_admin_styles' ) );
8
- }
9
-
10
- /**
11
- * @return SiteOrigin_Panels_Admin_Dashboard
12
- */
13
- public static function single() {
14
- static $single;
15
- return empty( $single ) ? $single = new self() : $single;
16
- }
17
-
18
- /**
19
- * Register the dashboard widget
20
- */
21
- public function register_dashboard_widgets(){
22
- if( function_exists( 'wp_dashboard_primary_output' ) ) {
23
- wp_add_dashboard_widget( 'so-dashboard-news', __( 'SiteOrigin Page Builder News', 'siteorigin-panels' ), array(
24
- $this,
25
- 'dashboard_overview_widget'
26
- ) );
27
-
28
- // Move Page Builder widget to the top
29
- global $wp_meta_boxes;
30
-
31
- $dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
32
- $ours = array( 'so-dashboard-news' => $dashboard['so-dashboard-news'] );
33
-
34
- $wp_meta_boxes['dashboard']['normal']['core'] = array_merge( $ours, $dashboard ); // WPCS: override ok.
35
- }
36
- }
37
-
38
- /**
39
- * Enqueue the dashboard styles
40
- */
41
- public function enqueue_admin_styles( $page ){
42
- $screen = get_current_screen();
43
- if( ! empty( $screen ) && $screen->id == 'dashboard' ) {
44
- wp_enqueue_style(
45
- 'so-panels-dashboard',
46
- siteorigin_panels_url( 'css/dashboard.css' ),
47
- array( 'wp-color-picker' ),
48
- SITEORIGIN_PANELS_VERSION
49
- );
50
- }
51
- }
52
-
53
- /**
54
- * Display the actual widget
55
- */
56
- public function dashboard_overview_widget(){
57
- $feeds = array(
58
- array(
59
- 'url' => 'https://siteorigin.com/feed/',
60
- 'items' => 4,
61
- 'show_summary' => 0,
62
- 'show_author' => 0,
63
- 'show_date' => 1,
64
- ),
65
- );
66
-
67
- wp_dashboard_primary_output( 'so_dashboard_widget_news', $feeds );
68
-
69
- if( function_exists( 'wp_print_community_events_markup' ) ) {
70
- ?>
71
- <p class="community-events-footer">
72
- <?php
73
- printf(
74
- '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
75
- esc_url( 'https://siteorigin.com/blog/' ),
76
- __( 'Blog', 'siteorigin-panels' ),
77
- /* translators: accessibility text */
78
- __( '(opens in a new window)', 'siteorigin-panels' )
79
- );
80
- echo ' | ';
81
-
82
- if( class_exists( 'SiteOrigin_Premium' ) ) {
83
- printf(
84
- '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-email-alt"></span></a>',
85
- esc_url( 'mailto:support@siteorigin.com' ),
86
- __( 'Email Support', 'siteorigin-panels' ),
87
- /* translators: accessibility text */
88
- __( '(email SiteOrigin support)', 'siteorigin-panels' )
89
- );
90
- }
91
- else {
92
- printf(
93
- '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
94
- esc_url( 'https://siteorigin.com/thread/' ),
95
- __( 'Support Forum', 'siteorigin-panels' ),
96
- /* translators: accessibility text */
97
- __( '(opens in a new window)', 'siteorigin-panels' )
98
- );
99
- }
100
-
101
- if ( SiteOrigin_Panels::display_premium_teaser() ) {
102
- echo ' | ';
103
- printf(
104
- '<a href="%1$s" target="_blank" rel="noopener noreferrer" style="color: #2ebd59">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
105
- /* translators: If a Rosetta site exists (e.g. https://es.wordpress.org/news/), then use that. Otherwise, leave untranslated. */
106
- esc_url( 'https://siteorigin.com/downloads/premium/' ),
107
- __( 'Get Premium', 'siteorigin-panels' ),
108
- /* translators: accessibility text */
109
- __( '(opens in a new window)', 'siteorigin-panels' )
110
- );
111
- }
112
- ?>
113
- </p>
114
- <?php
115
- }
116
- }
117
- }
1
+ <?php
2
+
3
+ class SiteOrigin_Panels_Admin_Dashboard {
4
+
5
+ function __construct() {
6
+ add_action( 'wp_dashboard_setup', array( $this, 'register_dashboard_widgets' ), 15 );
7
+ add_action( 'admin_print_styles', array( $this, 'enqueue_admin_styles' ) );
8
+ }
9
+
10
+ /**
11
+ * @return SiteOrigin_Panels_Admin_Dashboard
12
+ */
13
+ public static function single() {
14
+ static $single;
15
+ return empty( $single ) ? $single = new self() : $single;
16
+ }
17
+
18
+ /**
19
+ * Register the dashboard widget
20
+ */
21
+ public function register_dashboard_widgets(){
22
+ if( function_exists( 'wp_dashboard_primary_output' ) ) {
23
+ wp_add_dashboard_widget( 'so-dashboard-news', __( 'SiteOrigin Page Builder News', 'siteorigin-panels' ), array(
24
+ $this,
25
+ 'dashboard_overview_widget'
26
+ ) );
27
+
28
+ // Move Page Builder widget to the top
29
+ global $wp_meta_boxes;
30
+
31
+ $dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
32
+ $ours = array( 'so-dashboard-news' => $dashboard['so-dashboard-news'] );
33
+
34
+ $wp_meta_boxes['dashboard']['normal']['core'] = array_merge( $ours, $dashboard ); // WPCS: override ok.
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Enqueue the dashboard styles
40
+ */
41
+ public function enqueue_admin_styles( $page ){
42
+ $screen = get_current_screen();
43
+ if( ! empty( $screen ) && $screen->id == 'dashboard' ) {
44
+ wp_enqueue_style(
45
+ 'so-panels-dashboard',
46
+ siteorigin_panels_url( 'css/dashboard.css' ),
47
+ array( 'wp-color-picker' ),
48
+ SITEORIGIN_PANELS_VERSION
49
+ );
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Display the actual widget
55
+ */
56
+ public function dashboard_overview_widget(){
57
+ $feeds = array(
58
+ array(
59
+ 'url' => 'https://siteorigin.com/feed/',
60
+ 'items' => 4,
61
+ 'show_summary' => 0,
62
+ 'show_author' => 0,
63
+ 'show_date' => 1,
64
+ ),
65
+ );
66
+
67
+ wp_dashboard_primary_output( 'so_dashboard_widget_news', $feeds );
68
+
69
+ if( function_exists( 'wp_print_community_events_markup' ) ) {
70
+ ?>
71
+ <p class="community-events-footer">
72
+ <?php
73
+ printf(
74
+ '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
75
+ esc_url( 'https://siteorigin.com/blog/' ),
76
+ __( 'Blog', 'siteorigin-panels' ),
77
+ /* translators: accessibility text */
78
+ __( '(opens in a new window)', 'siteorigin-panels' )
79
+ );
80
+ echo ' | ';
81
+
82
+ if( class_exists( 'SiteOrigin_Premium' ) ) {
83
+ printf(
84
+ '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-email-alt"></span></a>',
85
+ esc_url( 'mailto:support@siteorigin.com' ),
86
+ __( 'Email Support', 'siteorigin-panels' ),
87
+ /* translators: accessibility text */
88
+ __( '(email SiteOrigin support)', 'siteorigin-panels' )
89
+ );
90
+ }
91
+ else {
92
+ printf(
93
+ '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
94
+ esc_url( 'https://siteorigin.com/thread/' ),
95
+ __( 'Support Forum', 'siteorigin-panels' ),
96
+ /* translators: accessibility text */
97
+ __( '(opens in a new window)', 'siteorigin-panels' )
98
+ );
99
+ }
100
+
101
+ if ( SiteOrigin_Panels::display_premium_teaser() ) {
102
+ echo ' | ';
103
+ printf(
104
+ '<a href="%1$s" target="_blank" rel="noopener noreferrer" style="color: #2ebd59">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
105
+ /* translators: If a Rosetta site exists (e.g. https://es.wordpress.org/news/), then use that. Otherwise, leave untranslated. */
106
+ esc_url( 'https://siteorigin.com/downloads/premium/' ),
107
+ __( 'Get Premium', 'siteorigin-panels' ),
108
+ /* translators: accessibility text */
109
+ __( '(opens in a new window)', 'siteorigin-panels' )
110
+ );
111
+ }
112
+ ?>
113
+ </p>
114
+ <?php
115
+ }
116
+ }
117
+ }
inc/admin-layouts.php CHANGED
@@ -1,494 +1,494 @@
1
- <?php
2
-
3
- /**
4
- * Class SiteOrigin_Panels_Admin
5
- *
6
- * Handles all the admin and database interactions.
7
- */
8
- class SiteOrigin_Panels_Admin_Layouts {
9
-
10
- const LAYOUT_URL = 'https://layouts.siteorigin.com/';
11
-
12
- function __construct() {
13
- // Filter all the available external layout directories.
14
- add_filter( 'siteorigin_panels_external_layout_directories', array( $this, 'filter_directories' ), 8 );
15
- // Filter all the available local layout folders.
16
- add_filter( 'siteorigin_panels_prebuilt_layouts', array( $this, 'get_local_layouts' ), 8 );
17
-
18
- add_action( 'wp_ajax_so_panels_layouts_query', array( $this, 'action_get_prebuilt_layouts' ) );
19
- add_action( 'wp_ajax_so_panels_get_layout', array( $this, 'action_get_prebuilt_layout' ) );
20
- add_action( 'wp_ajax_so_panels_import_layout', array( $this, 'action_import_layout' ) );
21
- add_action( 'wp_ajax_so_panels_export_layout', array( $this, 'action_export_layout' ) );
22
- add_action( 'wp_ajax_so_panels_directory_enable', array( $this, 'action_directory_enable' ) );
23
- }
24
-
25
- /**
26
- * @return SiteOrigin_Panels_Admin_Layouts
27
- */
28
- public static function single() {
29
- static $single;
30
- return empty( $single ) ? $single = new self() : $single;
31
- }
32
-
33
- /**
34
- * Add the main SiteOrigin layout directory
35
- */
36
- public function filter_directories( $directories ){
37
- if ( apply_filters( 'siteorigin_panels_layouts_directory_enabled', true ) ) {
38
- $directories['siteorigin'] = array(
39
- // The title of the layouts directory in the sidebar.
40
- 'title' => __( 'Layouts Directory', 'siteorigin-panels' ),
41
- // The URL of the directory.
42
- 'url' => self::LAYOUT_URL,
43
- // Any additional arguments to pass to the layouts server
44
- 'args' => array()
45
- );
46
- }
47
-
48
- return $directories;
49
- }
50
-
51
- /**
52
- * Get all the layout directories.
53
- *
54
- * @return array
55
- */
56
- public function get_directories(){
57
- $directories = apply_filters( 'siteorigin_panels_external_layout_directories', array() );
58
- if( empty( $directories ) || ! is_array( $directories ) ) {
59
- $directories = array();
60
- }
61
-
62
- return $directories;
63
- }
64
-
65
-
66
- /**
67
- * Looks through local folders in the active theme and any others filtered in by theme and plugins, to find JSON
68
- * prebuilt layouts.
69
- *
70
- */
71
- public function get_local_layouts() {
72
-
73
- // By default we'll look for layouts in a directory in the active theme
74
- $layout_folders = array( get_template_directory() . '/siteorigin-page-builder-layouts' );
75
-
76
- // And the child theme if there is one.
77
- if ( is_child_theme() ) {
78
- $layout_folders[] = get_stylesheet_directory() . '/siteorigin-page-builder-layouts';
79
- }
80
-
81
- // This allows themes and plugins to customize where we look for layouts.
82
- $layout_folders = apply_filters( 'siteorigin_panels_local_layouts_directories', $layout_folders );
83
-
84
- $layouts = array();
85
- foreach ( $layout_folders as $folder ) {
86
- $folder = realpath($folder);
87
- if ( file_exists( $folder ) && is_dir( $folder ) ) {
88
- $files = list_files( $folder, 1 );
89
- if ( empty( $files ) ) {
90
- continue;
91
- }
92
-
93
- foreach ( $files as $file ) {
94
-
95
- if ( function_exists( 'mime_content_type' ) ) {
96
- // get file mime type
97
- $mime_type = mime_content_type( $file );
98
-
99
- // Valid if text files.
100
- $valid_file_type = strpos( $mime_type, 'text/' ) === 0;
101
- } else {
102
- // If `mime_content_type` isn't available, just check file extension.
103
- $ext = pathinfo( $file, PATHINFO_EXTENSION );
104
-
105
- // skip files which don't have a `.json` extension.
106
- $valid_file_type = ! empty( $ext ) && $ext === 'json';
107
- }
108
-
109
- if ( ! $valid_file_type ) {
110
- continue;
111
- }
112
-
113
- // get file contents
114
- $file_contents = file_get_contents( $file );
115
-
116
- // skip if file_get_contents fails
117
- if ( $file_contents === false ) {
118
- continue;
119
- }
120
-
121
- // json decode
122
- $panels_data = json_decode( $file_contents, true );
123
-
124
- if ( ! empty( $panels_data ) ) {
125
- // get file name by stripping out folder path and .json extension
126
- $file_name = str_replace( array( $folder . '/', '.json' ), '', $file );
127
-
128
- // get name: check for id or name else use filename
129
- $panels_data['id'] = sanitize_title_with_dashes( $this->get_layout_id( $panels_data, $file_name ) );
130
-
131
- if ( empty( $panels_data['name'] ) ) {
132
- $panels_data['name'] = $file_name;
133
- }
134
-
135
- $panels_data['name'] = sanitize_text_field( $panels_data['name'] );
136
-
137
- // get screenshot: check for screenshot prop else try use image file with same filename.
138
- $panels_data['screenshot'] = $this->get_layout_file_screenshot( $panels_data, $folder, $file_name );
139
-
140
- // set item on layouts array
141
- $layouts[ $panels_data['id'] ] = $panels_data;
142
- }
143
- }
144
- }
145
- }
146
-
147
- return $layouts;
148
- }
149
-
150
- private function get_layout_id( $layout_data, $fallback ) {
151
- if ( ! empty( $layout_data['id'] ) ) {
152
- return $layout_data['id'];
153
- } else if ( ! empty( $layout_data['name'] ) ) {
154
- return $layout_data['name'];
155
- } else {
156
- return $fallback;
157
- }
158
- }
159
-
160
- private function get_layout_file_screenshot( $panels_data, $folder_path, $file_name ) {
161
- if ( ! empty( $panels_data['screenshot'] ) ) {
162
- return $panels_data['screenshot'];
163
- } else {
164
- $paths = glob( $folder_path . "/$file_name.{jpg,jpeg,gif,png}", GLOB_BRACE );
165
- // Highlander Condition. There can be only one.
166
- $screenshot_path = empty( $paths ) ? '' : wp_normalize_path( $paths[0] );
167
- $wp_content_dir = wp_normalize_path( WP_CONTENT_DIR );
168
- $screenshot_url = '';
169
- if ( file_exists( $screenshot_path ) &&
170
- strrpos( $screenshot_path, $wp_content_dir ) === 0 ) {
171
-
172
- $screenshot_url = str_replace( $wp_content_dir, content_url(), $screenshot_path );
173
- }
174
-
175
- return $screenshot_url;
176
- }
177
- }
178
-
179
- /**
180
- * Gets all the prebuilt layouts.
181
- */
182
- function action_get_prebuilt_layouts() {
183
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
184
- wp_die( __( 'Invalid request.', 'siteorigin-panels' ), 403 );
185
- }
186
-
187
- // Get any layouts that the current user could edit.
188
- header( 'content-type: application/json' );
189
-
190
- $type = ! empty( $_REQUEST['type'] ) ? $_REQUEST['type'] : 'directory-siteorigin';
191
- $search = ! empty( $_REQUEST['search'] ) ? trim( strtolower( $_REQUEST['search'] ) ) : '';
192
- $page_num = ! empty( $_REQUEST['page'] ) ? intval( $_REQUEST['page'] ) : 1;
193
-
194
- $return = array(
195
- 'title' => '',
196
- 'items' => array()
197
- );
198
- if ( $type == 'prebuilt' ) {
199
- $return['title'] = __( 'Theme Defined Layouts', 'siteorigin-panels' );
200
-
201
- // This is for theme bundled prebuilt directories
202
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
203
-
204
- foreach ( $layouts as $id => $vals ) {
205
- if ( ! empty( $search ) && strpos( strtolower( $vals['name'] ), $search ) === false ) {
206
- continue;
207
- }
208
-
209
- $return['items'][] = array(
210
- 'title' => $vals['name'],
211
- 'id' => $id,
212
- 'type' => 'prebuilt',
213
- 'description' => isset( $vals['description'] ) ? $vals['description'] : '',
214
- 'screenshot' => ! empty( $vals['screenshot'] ) ? $vals['screenshot'] : ''
215
- );
216
- }
217
-
218
- $return['max_num_pages'] = 1;
219
- } elseif ( substr( $type, 0, 10 ) == 'directory-' ) {
220
- $return['title'] = __( 'Layouts Directory', 'siteorigin-panels' );
221
-
222
- // This is a query of the prebuilt layout directory
223
- $query = array();
224
- if ( ! empty( $search ) ) {
225
- $query['search'] = $search;
226
- }
227
- $query['page'] = $page_num;
228
-
229
- $directory_id = str_replace( 'directory-', '', $type );
230
- $directories = $this->get_directories();
231
- $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
232
-
233
- if( empty( $directory ) ) {
234
- return false;
235
- }
236
-
237
- $url = add_query_arg( $query, $directory[ 'url' ] . 'wp-admin/admin-ajax.php?action=query_layouts' );
238
- if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
239
- $url = add_query_arg( $directory[ 'args' ], $url );
240
- }
241
-
242
- $url = apply_filters( 'siteorigin_panels_layouts_directory_url', $url );
243
- $response = wp_remote_get( $url );
244
-
245
- if ( is_array( $response ) && $response['response']['code'] == 200 ) {
246
- $results = json_decode( $response['body'], true );
247
- if ( ! empty( $results ) && ! empty( $results['items'] ) ) {
248
- foreach ( $results['items'] as $item ) {
249
- $item['id'] = $item['slug'];
250
- $item['type'] = $type;
251
-
252
- if( empty( $item['screenshot'] ) && ! empty( $item['preview'] ) ) {
253
- $preview_url = add_query_arg( 'screenshot', 'true', $item[ 'preview' ] );
254
- $item['screenshot'] = 'https://s.wordpress.com/mshots/v1/' . urlencode( $preview_url ) . '?w=700';
255
- }
256
-
257
- $return['items'][] = $item;
258
- }
259
- }
260
-
261
- $return['max_num_pages'] = $results['max_num_pages'];
262
- }
263
- } elseif ( strpos( $type, 'clone_' ) !== false ) {
264
- // Check that the user can view the given page types
265
- $post_type = get_post_type_object( str_replace( 'clone_', '', $type ) );
266
- if( empty( $post_type ) ) {
267
- return;
268
- }
269
-
270
- $return['title'] = sprintf( __( 'Clone %s', 'siteorigin-panels' ), esc_html( $post_type->labels->singular_name ) );
271
-
272
- global $wpdb;
273
- $user_can_read_private = ( $post_type->name == 'post' && current_user_can( 'read_private_posts' ) || ( $post_type->name == 'page' && current_user_can( 'read_private_pages' ) ) );
274
- $include_private = $user_can_read_private ? "OR posts.post_status = 'private' " : "";
275
-
276
- // Select only the posts with the given post type that also have panels_data
277
- $results = $wpdb->get_results( "
278
- SELECT SQL_CALC_FOUND_ROWS DISTINCT ID, post_title, meta.meta_value
279
- FROM {$wpdb->posts} AS posts
280
- JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
281
- WHERE
282
- posts.post_type = '" . esc_sql( $post_type->name ) . "'
283
- AND meta.meta_key = 'panels_data'
284
- " . ( ! empty( $search ) ? 'AND posts.post_title LIKE "%' . esc_sql( $search ) . '%"' : '' ) . "
285
- AND ( posts.post_status = 'publish' OR posts.post_status = 'draft' " . $include_private . ")
286
- ORDER BY post_date DESC
287
- LIMIT 16 OFFSET " . intval( ( $page_num - 1 ) * 16 ) );
288
- $total_posts = $wpdb->get_var( "SELECT FOUND_ROWS();" );
289
-
290
- foreach ( $results as $result ) {
291
- $thumbnail = get_the_post_thumbnail_url( $result->ID, array( 400, 300 ) );
292
- $return['items'][] = array(
293
- 'id' => $result->ID,
294
- 'title' => $result->post_title,
295
- 'type' => $type,
296
- 'screenshot' => ! empty( $thumbnail ) ? $thumbnail : ''
297
- );
298
- }
299
-
300
- $return['max_num_pages'] = ceil( $total_posts / 16 );
301
-
302
- } else {
303
- // An invalid type. Display an error message.
304
- }
305
-
306
- // Add the search part to the title
307
- if ( ! empty( $search ) ) {
308
- $return['title'] .= __( ' - Results For:', 'siteorigin-panels' ) . ' <em>' . esc_html( $search ) . '</em>';
309
- }
310
-
311
- echo json_encode( $return );
312
-
313
- wp_die();
314
- }
315
-
316
- /**
317
- * Ajax handler to get an individual prebuilt layout
318
- */
319
- function action_get_prebuilt_layout() {
320
- if ( empty( $_REQUEST['type'] ) ) {
321
- wp_die();
322
- }
323
- if ( empty( $_REQUEST['lid'] ) ) {
324
- wp_die();
325
- }
326
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
327
- wp_die();
328
- }
329
-
330
- header( 'content-type: application/json' );
331
- $panels_data = array();
332
- $raw_panels_data = false;
333
-
334
- if ( $_REQUEST['type'] == 'prebuilt' ) {
335
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
336
- $lid = ! empty( $_REQUEST['lid'] ) ? $_REQUEST['lid'] : false;
337
-
338
- if ( empty( $lid ) || empty( $layouts[ $lid ] ) ) {
339
- wp_send_json_error( array(
340
- 'error' => true,
341
- 'message' => __( 'Missing layout ID or no such layout exists', 'siteorigin-panels' ),
342
- ) );
343
- }
344
-
345
- $layout = $layouts[ $_REQUEST['lid'] ];
346
-
347
- // Fix the format of this layout
348
- if( !empty( $layout[ 'filename' ] ) ) {
349
- $filename = $layout[ 'filename' ];
350
- // Only accept filenames that end with .json
351
- if( substr( $filename, -5, 5 ) === '.json' && file_exists( $filename ) ) {
352
- $panels_data = json_decode( file_get_contents( $filename ), true );
353
- $layout[ 'widgets' ] = ! empty( $panels_data[ 'widgets' ] ) ? $panels_data[ 'widgets' ] : array();
354
- $layout[ 'grids' ] = ! empty( $panels_data[ 'grids' ] ) ? $panels_data[ 'grids' ] : array();
355
- $layout[ 'grid_cells' ] = ! empty( $panels_data[ 'grid_cells' ] ) ? $panels_data[ 'grid_cells' ] : array();
356
- }
357
- }
358
-
359
- // A theme or plugin could use this to change the data in the layout
360
- $panels_data = apply_filters( 'siteorigin_panels_prebuilt_layout', $layout, $lid );
361
-
362
- // Remove all the layout specific attributes
363
- if ( isset( $panels_data['name'] ) ) unset( $panels_data['name'] );
364
- if ( isset( $panels_data['screenshot'] ) ) unset( $panels_data['screenshot'] );
365
- if ( isset( $panels_data['filename'] ) ) unset( $panels_data['filename'] );
366
-
367
- $raw_panels_data = true;
368
-
369
- } elseif ( substr( $_REQUEST['type'], 0, 10 ) == 'directory-' ) {
370
- $directory_id = str_replace( 'directory-', '', $_REQUEST['type'] );
371
- $directories = $this->get_directories();
372
- $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
373
-
374
- if( ! empty( $directory ) ) {
375
- $url = $directory[ 'url' ] . 'layout/' . urlencode( $_REQUEST[ 'lid' ] ) . '/?action=download';
376
- if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
377
- $url = add_query_arg( $directory[ 'args' ], $url );
378
- }
379
-
380
- $response = wp_remote_get( $url );
381
- if ( $response['response']['code'] == 200 ) {
382
- // For now, we'll just pretend to load this
383
- $panels_data = json_decode( $response['body'], true );
384
- } else {
385
- wp_send_json_error( array(
386
- 'error' => true,
387
- 'message' => __( 'There was a problem fetching the layout. Please try again later.', 'siteorigin-panels' ),
388
- ) );
389
- }
390
- }
391
- $raw_panels_data = true;
392
-
393
- } elseif ( current_user_can( 'edit_post', $_REQUEST['lid'] ) ) {
394
- $panels_data = get_post_meta( $_REQUEST['lid'], 'panels_data', true );
395
-
396
- // Clear id and timestamp for SO widgets to prevent 'newer content version' notification in widget forms.
397
- foreach ( $panels_data['widgets'] as &$widget ) {
398
- unset( $widget['_sow_form_id'] );
399
- unset( $widget['_sow_form_timestamp'] );
400
- }
401
- }
402
-
403
- if( $raw_panels_data ) {
404
- // This panels_data is flagged as raw, so it needs to be processed.
405
- $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
406
- $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
407
- }
408
-
409
- wp_send_json_success( $panels_data );
410
- }
411
-
412
- /**
413
- * Ajax handler to import a layout
414
- */
415
- function action_import_layout() {
416
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
417
- wp_die();
418
- }
419
-
420
- if ( ! empty( $_FILES['panels_import_data']['tmp_name'] ) ) {
421
- header( 'content-type:application/json' );
422
- $json = file_get_contents( $_FILES['panels_import_data']['tmp_name'] );
423
- $panels_data = json_decode( $json, true );
424
- $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
425
- $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
426
- $json = json_encode( $panels_data );
427
- @unlink( $_FILES['panels_import_data']['tmp_name'] );
428
- echo $json;
429
- }
430
- wp_die();
431
- }
432
-
433
- /**
434
- * Export a given layout as a JSON file.
435
- */
436
- function action_export_layout() {
437
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
438
- wp_die();
439
- }
440
-
441
- $export_data = wp_unslash( $_POST['panels_export_data'] );
442
-
443
- $decoded_export_data = json_decode( $export_data, true );
444
-
445
- if ( ! empty( $decoded_export_data['name'] ) ) {
446
- $decoded_export_data['id'] = sanitize_title_with_dashes( $decoded_export_data['name'] );
447
- $filename = $decoded_export_data['id'];
448
- } else {
449
- $filename = 'layout-' . date( 'dmY' );
450
- }
451
-
452
-
453
- header( 'content-type: application/json' );
454
- header( "Content-Disposition: attachment; filename=$filename.json" );
455
-
456
- echo $export_data;
457
-
458
- wp_die();
459
- }
460
-
461
- /**
462
- * Enable the directory.
463
- */
464
- function action_directory_enable() {
465
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
466
- wp_die();
467
- }
468
- $user = get_current_user_id();
469
- update_user_meta( $user, 'so_panels_directory_enabled', true );
470
- wp_die();
471
- }
472
-
473
- /**
474
- * Load a layout from a json file
475
- *
476
- * @param $id
477
- * @param $name
478
- * @param $json_file
479
- * @param bool $screenshot
480
- *
481
- * @return array The data for the layout
482
- */
483
- public static function load_layout($id, $name, $json_file, $screenshot = false) {
484
- $layout_data = json_decode(file_get_contents($json_file), true);
485
- $layout_data = apply_filters('siteorigin_panels_load_layout_' . $id, $layout_data);
486
-
487
- $layout_data = array_merge(array(
488
- 'name' => $name,
489
- 'screenshot' => $screenshot,
490
- ), $layout_data);
491
-
492
- return $layout_data;
493
- }
494
- }
1
+ <?php
2
+
3
+ /**
4
+ * Class SiteOrigin_Panels_Admin
5
+ *
6
+ * Handles all the admin and database interactions.
7
+ */
8
+ class SiteOrigin_Panels_Admin_Layouts {
9
+
10
+ const LAYOUT_URL = 'https://layouts.siteorigin.com/';
11
+
12
+ function __construct() {
13
+ // Filter all the available external layout directories.
14
+ add_filter( 'siteorigin_panels_external_layout_directories', array( $this, 'filter_directories' ), 8 );
15
+ // Filter all the available local layout folders.
16
+ add_filter( 'siteorigin_panels_prebuilt_layouts', array( $this, 'get_local_layouts' ), 8 );
17
+
18
+ add_action( 'wp_ajax_so_panels_layouts_query', array( $this, 'action_get_prebuilt_layouts' ) );
19
+ add_action( 'wp_ajax_so_panels_get_layout', array( $this, 'action_get_prebuilt_layout' ) );
20
+ add_action( 'wp_ajax_so_panels_import_layout', array( $this, 'action_import_layout' ) );
21
+ add_action( 'wp_ajax_so_panels_export_layout', array( $this, 'action_export_layout' ) );
22
+ add_action( 'wp_ajax_so_panels_directory_enable', array( $this, 'action_directory_enable' ) );
23
+ }
24
+
25
+ /**
26
+ * @return SiteOrigin_Panels_Admin_Layouts
27
+ */
28
+ public static function single() {
29
+ static $single;
30
+ return empty( $single ) ? $single = new self() : $single;
31
+ }
32
+
33
+ /**
34
+ * Add the main SiteOrigin layout directory
35
+ */
36
+ public function filter_directories( $directories ){
37
+ if ( apply_filters( 'siteorigin_panels_layouts_directory_enabled', true ) ) {
38
+ $directories['siteorigin'] = array(
39
+ // The title of the layouts directory in the sidebar.
40
+ 'title' => __( 'Layouts Directory', 'siteorigin-panels' ),
41
+ // The URL of the directory.
42
+ 'url' => self::LAYOUT_URL,
43
+ // Any additional arguments to pass to the layouts server
44
+ 'args' => array()
45
+ );
46
+ }
47
+
48
+ return $directories;
49
+ }
50
+
51
+ /**
52
+ * Get all the layout directories.
53
+ *
54
+ * @return array
55
+ */
56
+ public function get_directories(){
57
+ $directories = apply_filters( 'siteorigin_panels_external_layout_directories', array() );
58
+ if( empty( $directories ) || ! is_array( $directories ) ) {
59
+ $directories = array();
60
+ }
61
+
62
+ return $directories;
63
+ }
64
+
65
+
66
+ /**
67
+ * Looks through local folders in the active theme and any others filtered in by theme and plugins, to find JSON
68
+ * prebuilt layouts.
69
+ *
70
+ */
71
+ public function get_local_layouts() {
72
+
73
+ // By default we'll look for layouts in a directory in the active theme
74
+ $layout_folders = array( get_template_directory() . '/siteorigin-page-builder-layouts' );
75
+
76
+ // And the child theme if there is one.
77
+ if ( is_child_theme() ) {
78
+ $layout_folders[] = get_stylesheet_directory() . '/siteorigin-page-builder-layouts';
79
+ }
80
+
81
+ // This allows themes and plugins to customize where we look for layouts.
82
+ $layout_folders = apply_filters( 'siteorigin_panels_local_layouts_directories', $layout_folders );
83
+
84
+ $layouts = array();
85
+ foreach ( $layout_folders as $folder ) {
86
+ $folder = realpath($folder);
87
+ if ( file_exists( $folder ) && is_dir( $folder ) ) {
88
+ $files = list_files( $folder, 1 );
89
+ if ( empty( $files ) ) {
90
+ continue;
91
+ }
92
+
93
+ foreach ( $files as $file ) {
94
+
95
+ if ( function_exists( 'mime_content_type' ) ) {
96
+ // get file mime type
97
+ $mime_type = mime_content_type( $file );
98
+
99
+ // Valid if text files.
100
+ $valid_file_type = strpos( $mime_type, 'text/' ) === 0;
101
+ } else {
102
+ // If `mime_content_type` isn't available, just check file extension.
103
+ $ext = pathinfo( $file, PATHINFO_EXTENSION );
104
+
105
+ // skip files which don't have a `.json` extension.
106
+ $valid_file_type = ! empty( $ext ) && $ext === 'json';
107
+ }
108
+
109
+ if ( ! $valid_file_type ) {
110
+ continue;
111
+ }
112
+
113
+ // get file contents
114
+ $file_contents = file_get_contents( $file );
115
+
116
+ // skip if file_get_contents fails
117
+ if ( $file_contents === false ) {
118
+ continue;
119
+ }
120
+
121
+ // json decode
122
+ $panels_data = json_decode( $file_contents, true );
123
+
124
+ if ( ! empty( $panels_data ) ) {
125
+ // get file name by stripping out folder path and .json extension
126
+ $file_name = str_replace( array( $folder . '/', '.json' ), '', $file );
127
+
128
+ // get name: check for id or name else use filename
129
+ $panels_data['id'] = sanitize_title_with_dashes( $this->get_layout_id( $panels_data, $file_name ) );
130
+
131
+ if ( empty( $panels_data['name'] ) ) {
132
+ $panels_data['name'] = $file_name;
133
+ }
134
+
135
+ $panels_data['name'] = sanitize_text_field( $panels_data['name'] );
136
+
137
+ // get screenshot: check for screenshot prop else try use image file with same filename.
138
+ $panels_data['screenshot'] = $this->get_layout_file_screenshot( $panels_data, $folder, $file_name );
139
+
140
+ // set item on layouts array
141
+ $layouts[ $panels_data['id'] ] = $panels_data;
142
+ }
143
+ }
144
+ }
145
+ }
146
+
147
+ return $layouts;
148
+ }
149
+
150
+ private function get_layout_id( $layout_data, $fallback ) {
151
+ if ( ! empty( $layout_data['id'] ) ) {
152
+ return $layout_data['id'];
153
+ } else if ( ! empty( $layout_data['name'] ) ) {
154
+ return $layout_data['name'];
155
+ } else {
156
+ return $fallback;
157
+ }
158
+ }
159
+
160
+ private function get_layout_file_screenshot( $panels_data, $folder_path, $file_name ) {
161
+ if ( ! empty( $panels_data['screenshot'] ) ) {
162
+ return $panels_data['screenshot'];
163
+ } else {
164
+ $paths = glob( $folder_path . "/$file_name.{jpg,jpeg,gif,png}", GLOB_BRACE );
165
+ // Highlander Condition. There can be only one.
166
+ $screenshot_path = empty( $paths ) ? '' : wp_normalize_path( $paths[0] );
167
+ $wp_content_dir = wp_normalize_path( WP_CONTENT_DIR );
168
+ $screenshot_url = '';
169
+ if ( file_exists( $screenshot_path ) &&
170
+ strrpos( $screenshot_path, $wp_content_dir ) === 0 ) {
171
+
172
+ $screenshot_url = str_replace( $wp_content_dir, content_url(), $screenshot_path );
173
+ }
174
+
175
+ return $screenshot_url;
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Gets all the prebuilt layouts.
181
+ */
182
+ function action_get_prebuilt_layouts() {
183
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
184
+ wp_die( __( 'Invalid request.', 'siteorigin-panels' ), 403 );
185
+ }
186
+
187
+ // Get any layouts that the current user could edit.
188
+ header( 'content-type: application/json' );
189
+
190
+ $type = ! empty( $_REQUEST['type'] ) ? $_REQUEST['type'] : 'directory-siteorigin';
191
+ $search = ! empty( $_REQUEST['search'] ) ? trim( strtolower( $_REQUEST['search'] ) ) : '';
192
+ $page_num = ! empty( $_REQUEST['page'] ) ? intval( $_REQUEST['page'] ) : 1;
193
+
194
+ $return = array(
195
+ 'title' => '',
196
+ 'items' => array()
197
+ );
198
+ if ( $type == 'prebuilt' ) {
199
+ $return['title'] = __( 'Theme Defined Layouts', 'siteorigin-panels' );
200
+
201
+ // This is for theme bundled prebuilt directories
202
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
203
+
204
+ foreach ( $layouts as $id => $vals ) {
205
+ if ( ! empty( $search ) && strpos( strtolower( $vals['name'] ), $search ) === false ) {
206
+ continue;
207
+ }
208
+
209
+ $return['items'][] = array(
210
+ 'title' => $vals['name'],
211
+ 'id' => $id,
212
+ 'type' => 'prebuilt',
213
+ 'description' => isset( $vals['description'] ) ? $vals['description'] : '',
214
+ 'screenshot' => ! empty( $vals['screenshot'] ) ? $vals['screenshot'] : ''
215
+ );
216
+ }
217
+
218
+ $return['max_num_pages'] = 1;
219
+ } elseif ( substr( $type, 0, 10 ) == 'directory-' ) {
220
+ $return['title'] = __( 'Layouts Directory', 'siteorigin-panels' );
221
+
222
+ // This is a query of the prebuilt layout directory
223
+ $query = array();
224
+ if ( ! empty( $search ) ) {
225
+ $query['search'] = $search;
226
+ }
227
+ $query['page'] = $page_num;
228
+
229
+ $directory_id = str_replace( 'directory-', '', $type );
230
+ $directories = $this->get_directories();
231
+ $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
232
+
233
+ if( empty( $directory ) ) {
234
+ return false;
235
+ }
236
+
237
+ $url = add_query_arg( $query, $directory[ 'url' ] . 'wp-admin/admin-ajax.php?action=query_layouts' );
238
+ if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
239
+ $url = add_query_arg( $directory[ 'args' ], $url );
240
+ }
241
+
242
+ $url = apply_filters( 'siteorigin_panels_layouts_directory_url', $url );
243
+ $response = wp_remote_get( $url );
244
+
245
+ if ( is_array( $response ) && $response['response']['code'] == 200 ) {
246
+ $results = json_decode( $response['body'], true );
247
+ if ( ! empty( $results ) && ! empty( $results['items'] ) ) {
248
+ foreach ( $results['items'] as $item ) {
249
+ $item['id'] = $item['slug'];
250
+ $item['type'] = $type;
251
+
252
+ if( empty( $item['screenshot'] ) && ! empty( $item['preview'] ) ) {
253
+ $preview_url = add_query_arg( 'screenshot', 'true', $item[ 'preview' ] );
254
+ $item['screenshot'] = 'https://s.wordpress.com/mshots/v1/' . urlencode( $preview_url ) . '?w=700';
255
+ }
256
+
257
+ $return['items'][] = $item;
258
+ }
259
+ }
260
+
261
+ $return['max_num_pages'] = $results['max_num_pages'];
262
+ }
263
+ } elseif ( strpos( $type, 'clone_' ) !== false ) {
264
+ // Check that the user can view the given page types
265
+ $post_type = get_post_type_object( str_replace( 'clone_', '', $type ) );
266
+ if( empty( $post_type ) ) {
267
+ return;
268
+ }
269
+
270
+ $return['title'] = sprintf( __( 'Clone %s', 'siteorigin-panels' ), esc_html( $post_type->labels->singular_name ) );
271
+
272
+ global $wpdb;
273
+ $user_can_read_private = ( $post_type->name == 'post' && current_user_can( 'read_private_posts' ) || ( $post_type->name == 'page' && current_user_can( 'read_private_pages' ) ) );
274
+ $include_private = $user_can_read_private ? "OR posts.post_status = 'private' " : "";
275
+
276
+ // Select only the posts with the given post type that also have panels_data
277
+ $results = $wpdb->get_results( "
278
+ SELECT SQL_CALC_FOUND_ROWS DISTINCT ID, post_title, meta.meta_value
279
+ FROM {$wpdb->posts} AS posts
280
+ JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
281
+ WHERE
282
+ posts.post_type = '" . esc_sql( $post_type->name ) . "'
283
+ AND meta.meta_key = 'panels_data'
284
+ " . ( ! empty( $search ) ? 'AND posts.post_title LIKE "%' . esc_sql( $search ) . '%"' : '' ) . "
285
+ AND ( posts.post_status = 'publish' OR posts.post_status = 'draft' " . $include_private . ")
286
+ ORDER BY post_date DESC
287
+ LIMIT 16 OFFSET " . intval( ( $page_num - 1 ) * 16 ) );
288
+ $total_posts = $wpdb->get_var( "SELECT FOUND_ROWS();" );
289
+
290
+ foreach ( $results as $result ) {
291
+ $thumbnail = get_the_post_thumbnail_url( $result->ID, array( 400, 300 ) );
292
+ $return['items'][] = array(
293
+ 'id' => $result->ID,
294
+ 'title' => $result->post_title,
295
+ 'type' => $type,
296
+ 'screenshot' => ! empty( $thumbnail ) ? $thumbnail : ''
297
+ );
298
+ }
299
+
300
+ $return['max_num_pages'] = ceil( $total_posts / 16 );
301
+
302
+ } else {
303
+ // An invalid type. Display an error message.
304
+ }
305
+
306
+ // Add the search part to the title
307
+ if ( ! empty( $search ) ) {
308
+ $return['title'] .= __( ' - Results For:', 'siteorigin-panels' ) . ' <em>' . esc_html( $search ) . '</em>';
309
+ }
310
+
311
+ echo json_encode( $return );
312
+
313
+ wp_die();
314
+ }
315
+
316
+ /**
317
+ * Ajax handler to get an individual prebuilt layout
318
+ */
319
+ function action_get_prebuilt_layout() {
320
+ if ( empty( $_REQUEST['type'] ) ) {
321
+ wp_die();
322
+ }
323
+ if ( empty( $_REQUEST['lid'] ) ) {
324
+ wp_die();
325
+ }
326
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
327
+ wp_die();
328
+ }
329
+
330
+ header( 'content-type: application/json' );
331
+ $panels_data = array();
332
+ $raw_panels_data = false;
333
+
334
+ if ( $_REQUEST['type'] == 'prebuilt' ) {
335
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
336
+ $lid = ! empty( $_REQUEST['lid'] ) ? $_REQUEST['lid'] : false;
337
+
338
+ if ( empty( $lid ) || empty( $layouts[ $lid ] ) ) {
339
+ wp_send_json_error( array(
340
+ 'error' => true,
341
+ 'message' => __( 'Missing layout ID or no such layout exists', 'siteorigin-panels' ),
342
+ ) );
343
+ }
344
+
345
+ $layout = $layouts[ $_REQUEST['lid'] ];
346
+
347
+ // Fix the format of this layout
348
+ if( !empty( $layout[ 'filename' ] ) ) {
349
+ $filename = $layout[ 'filename' ];
350
+ // Only accept filenames that end with .json
351
+ if( substr( $filename, -5, 5 ) === '.json' && file_exists( $filename ) ) {
352
+ $panels_data = json_decode( file_get_contents( $filename ), true );
353
+ $layout[ 'widgets' ] = ! empty( $panels_data[ 'widgets' ] ) ? $panels_data[ 'widgets' ] : array();
354
+ $layout[ 'grids' ] = ! empty( $panels_data[ 'grids' ] ) ? $panels_data[ 'grids' ] : array();
355
+ $layout[ 'grid_cells' ] = ! empty( $panels_data[ 'grid_cells' ] ) ? $panels_data[ 'grid_cells' ] : array();
356
+ }
357
+ }
358
+
359
+ // A theme or plugin could use this to change the data in the layout
360
+ $panels_data = apply_filters( 'siteorigin_panels_prebuilt_layout', $layout, $lid );
361
+
362
+ // Remove all the layout specific attributes
363
+ if ( isset( $panels_data['name'] ) ) unset( $panels_data['name'] );
364
+ if ( isset( $panels_data['screenshot'] ) ) unset( $panels_data['screenshot'] );
365
+ if ( isset( $panels_data['filename'] ) ) unset( $panels_data['filename'] );
366
+
367
+ $raw_panels_data = true;
368
+
369
+ } elseif ( substr( $_REQUEST['type'], 0, 10 ) == 'directory-' ) {
370
+ $directory_id = str_replace( 'directory-', '', $_REQUEST['type'] );
371
+ $directories = $this->get_directories();
372
+ $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
373
+
374
+ if( ! empty( $directory ) ) {
375
+ $url = $directory[ 'url' ] . 'layout/' . urlencode( $_REQUEST[ 'lid' ] ) . '/?action=download';
376
+ if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
377
+ $url = add_query_arg( $directory[ 'args' ], $url );
378
+ }
379
+
380
+ $response = wp_remote_get( $url );
381
+ if ( $response['response']['code'] == 200 ) {
382
+ // For now, we'll just pretend to load this
383
+ $panels_data = json_decode( $response['body'], true );
384
+ } else {
385
+ wp_send_json_error( array(
386
+ 'error' => true,
387
+ 'message' => __( 'There was a problem fetching the layout. Please try again later.', 'siteorigin-panels' ),
388
+ ) );
389
+ }
390
+ }
391
+ $raw_panels_data = true;
392
+
393
+ } elseif ( current_user_can( 'edit_post', $_REQUEST['lid'] ) ) {
394
+ $panels_data = get_post_meta( $_REQUEST['lid'], 'panels_data', true );
395
+
396
+ // Clear id and timestamp for SO widgets to prevent 'newer content version' notification in widget forms.
397
+ foreach ( $panels_data['widgets'] as &$widget ) {
398
+ unset( $widget['_sow_form_id'] );
399
+ unset( $widget['_sow_form_timestamp'] );
400
+ }
401
+ }
402
+
403
+ if( $raw_panels_data ) {
404
+ // This panels_data is flagged as raw, so it needs to be processed.
405
+ $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
406
+ $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
407
+ }
408
+
409
+ wp_send_json_success( $panels_data );
410
+ }
411
+
412
+ /**
413
+ * Ajax handler to import a layout
414
+ */
415
+ function action_import_layout() {
416
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
417
+ wp_die();
418
+ }
419
+
420
+ if ( ! empty( $_FILES['panels_import_data']['tmp_name'] ) ) {
421
+ header( 'content-type:application/json' );
422
+ $json = file_get_contents( $_FILES['panels_import_data']['tmp_name'] );
423
+ $panels_data = json_decode( $json, true );
424
+ $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
425
+ $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
426
+ $json = json_encode( $panels_data );
427
+ @unlink( $_FILES['panels_import_data']['tmp_name'] );
428
+ echo $json;
429
+ }
430
+ wp_die();
431
+ }
432
+
433
+ /**
434
+ * Export a given layout as a JSON file.
435
+ */
436
+ function action_export_layout() {
437
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
438
+ wp_die();
439
+ }
440
+
441
+ $export_data = wp_unslash( $_POST['panels_export_data'] );
442
+
443
+ $decoded_export_data = json_decode( $export_data, true );
444
+
445
+ if ( ! empty( $decoded_export_data['name'] ) ) {
446
+ $decoded_export_data['id'] = sanitize_title_with_dashes( $decoded_export_data['name'] );
447
+ $filename = $decoded_export_data['id'];
448
+ } else {
449
+ $filename = 'layout-' . date( 'dmY' );
450
+ }
451
+
452
+
453
+ header( 'content-type: application/json' );
454
+ header( "Content-Disposition: attachment; filename=$filename.json" );
455
+
456
+ echo $export_data;
457
+
458
+ wp_die();
459
+ }
460
+
461
+ /**
462
+ * Enable the directory.
463
+ */
464
+ function action_directory_enable() {
465
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
466
+ wp_die();
467
+ }
468
+ $user = get_current_user_id();
469
+ update_user_meta( $user, 'so_panels_directory_enabled', true );
470
+ wp_die();
471
+ }
472
+
473
+ /**
474
+ * Load a layout from a json file
475
+ *
476
+ * @param $id
477
+ * @param $name
478
+ * @param $json_file
479
+ * @param bool $screenshot
480
+ *
481
+ * @return array The data for the layout
482
+ */
483
+ public static function load_layout($id, $name, $json_file, $screenshot = false) {
484
+ $layout_data = json_decode(file_get_contents($json_file), true);
485
+ $layout_data = apply_filters('siteorigin_panels_load_layout_' . $id, $layout_data);
486
+
487
+ $layout_data = array_merge(array(
488
+ 'name' => $name,
489
+ 'screenshot' => $screenshot,
490
+ ), $layout_data);
491
+
492
+ return $layout_data;
493
+ }
494
+ }
inc/admin-tutorials.php DELETED
@@ -1,50 +0,0 @@
1
- <?php
2
-
3
- class SiteOrigin_Panels_Admin_Tutorials {
4
-
5
- function __construct() {
6
- add_action( 'wp_ajax_so_panels_get_tutorials', array( $this, 'action_get_tutorials' ) );
7
- }
8
-
9
- /**
10
- * @return SiteOrigin_Panels_Admin_Tutorials
11
- */
12
- public static function single() {
13
- static $single;
14
- return empty( $single ) ? $single = new self() : $single;
15
- }
16
-
17
- /**
18
- * Get the latest tutorials from SiteOrigin
19
- */
20
- public function action_get_tutorials(){
21
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
22
- wp_die();
23
- }
24
-
25
- $user = get_current_user_id();
26
- update_user_meta( $user, 'so_panels_tutorials_enabled', true );
27
-
28
- header( 'content-type:application/json' );
29
-
30
- $tutorials = get_transient( 'siteorigin_panels_tutorials' );
31
-
32
- if( empty( $tutorials ) ) {
33
- $response = wp_remote_get('https://siteorigin.com/wp-json/siteorigin/v1/tutorials/page-builder/');
34
- if ( is_array( $response ) && $response['response']['code'] == 200 ) {
35
- $tutorials = json_decode( $response['body'] );
36
- set_transient( 'siteorigin_panels_tutorials', $tutorials, 86400 );
37
- }
38
- else {
39
- $tutorials = array(
40
- 'error' => __( 'Error loading latest tutorials. Please try again after a few minutes.', 'siteorigin-panels' ),
41
- );
42
- }
43
- }
44
-
45
- echo json_encode( $tutorials );
46
-
47
- wp_die();
48
- }
49
-
50
- }