HEX
Server: Apache
System: Linux webm005.cluster121.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User: adventp (418412)
PHP: 7.4.33
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/adventp/www/wp-content/plugins/js_composer/assets/js/backend/composer-storage.js
/* =========================================================
 * composer-storage.js 1
 * =========================================================
 * Copyright 2013 Wpbakery
 *
 * WPBakery Page Builder backbone/underscore Storage hidden field
 * ========================================================= */
(function ( $ ) {
	'use strict';
	vc.debug = false;
	/**
	 * Shortcodes mapping settings.
	 * @type {Object}
	 */
	vc.map = _.isUndefined( window.vc_mapper ) ? {} : window.vc_mapper; // TODO: check with frontend why in frontend user user_mapper

	/**
	 * Shortcode Roles Based on general settings
	 * @since 4.5
	 *
	 * @type {{}}
	 */
	vc.roles = _.isUndefined( window.vc_roles ) ? {} : window.vc_roles;

	/**
	 * @constructor
	 */
	vc.Storage = function () {
		this.data = {};
	};
	/**
	 * CRUD methods for content management.
	 * @type {Object}
	 */
	vc.Storage.prototype = {
		url: window.ajaxurl,
		checksum: false,
		locked: false,
		isChanged: false,
		/**
		 * Create new object in storage. Require to define model name because system uses only one hidden field with
		 * serialized json object.
		 * @param model - Backbone.Model object
		 * @return {*} - Backbone.Model object
		 */
		create: function ( model ) {
			if ( !model.id ) {
				model.id = model.attributes.id = vc_guid();
			}
			this.data[ model.id ] = model.toJSON();
			// optimize root update
			this.setModelRoot( model.id );
			this.save();
			return model;
		},
		/**
		 * Optimization methods
		 */
		// {{ Methods allows lock/unlock data parsing into shortcodes and saving it in wp editor.
		lock: function () {
			this.locked = true;
		},
		unlock: function () {
			this.locked = false;
		},
		// }}
		setModelRoot: function ( id ) {
			var data = this.data[ id ];
			if ( _.isString( data.parent_id ) && _.isObject( this.data[ data.parent_id ] ) ) {
				data.root_id = this.data[ data.parent_id ].root_id;
			}
			if ( _.isObject( this.data[ data.root_id ] ) ) {
				this.data[ data.root_id ].html = false;
			}
		},
		/**
		 * Update object in storage.
		 * @param model
		 * @return {*}
		 */
		update: function ( model ) {
			this.data[ model.id ] = model.toJSON();
			this.setModelRoot( model.id );
			this.save();
			return model;
		},
		/**
		 * Remove record from storage
		 * @param model
		 * @return {*}
		 */
		destroy: function ( model ) {
			if ( !_.isUndefined( this.data[ model.id ] ) && !_.isUndefined( this.data[ model.id ].root_id ) && _.isObject(
				this.data[ this.data[ model.id ].root_id ] ) ) {
				this.data[ this.data[ model.id ].root_id ].html = false;
			}
			if ( !_.isUndefined( this.data[ model.id ] ) ) {
				delete this.data[ model.id ];
			}
			this.save();
			return model;
		},
		/**
		 * Find record by id
		 * @param model_id - id of model.
		 * @return {*} - object
		 */
		find: function ( model_id ) {
			return this.data[ model_id ];
		},
		/**
		 * Find all records in storage. Used by fetch.
		 * @return {*}
		 */
		findAll: function () {
			this.fetch();
			return _.values( this.data );
		},
		/**
		 * Find all root models which are sorted by order field.
		 * @return {*}
		 */
		findAllRootSorted: function () {
			var models = _.filter( _.values( this.data ), function ( model ) {
				return false === model.parent_id;
			} );
			return _.sortBy( models, function ( model ) {
				return model.order;
			} );
		},
		/***
		 * Escape double quotes and square brackets in params value.
		 * @param value
		 * @return string
		 */
		escapeParam: function ( value ) {
			if ( _.isUndefined( value ) || _.isNull( value ) || !value.toString ) {
				return '';
			}
			return value.toString().replace( /"/g, '``' ).replace( /\[/g, '`{`' ).replace( /\]/g, '`}`' );
		},
		/**
		 * Unescape double quotes and square brackets in params value.
		 * @param value
		 * @return {*}
		 */
		unescapeParam: function ( value ) {
			value = value.replace( /\`{\`/g, '[' ).replace( /\`}\`/g, ']' ).replace( /(\`{2})/g, '"' );
			value = vc_wpnop( value );
			return value;
		},
		/**
		 * Converts model data to wordpress shortcode.
		 * @param model
		 * @return {*}
		 */
		storageCreateShortcodeString: function ( model ) {
			var mapped, data, tag, params, content, paramsForString, mergedParams, isContainer;

			tag = model.get( 'shortcode' );
			params = _.extend( {}, model.get( 'params' ) );
			paramsForString = {};
			mergedParams = vc.getMergedParams( tag, params );
			_.each( mergedParams, function ( value, key ) {
				paramsForString[ key ] = this.escapeParam( value );
			}, this );
			mapped = vc.getMapped( tag );
			isContainer = _.isObject( mapped ) && ((_.isBoolean( mapped.is_container ) && true === mapped.is_container) || !_.isEmpty(
				mapped.as_parent ));
			content = this._storageGetShortcodeContent( model );
			data = {
				tag: tag,
				attrs: paramsForString,
				content: content,
				type: _.isUndefined( vc.getParamSettings( tag, 'content' ) ) && !isContainer ? 'single' : ''
			};
			model.trigger( 'stringify', model, data );

			return wp.shortcode.string( data );
		},
		/**
		 * Save data in hidden field.
		 * @return {Boolean}
		 */
		save: function () {
			if ( this.locked ) {
				this.locked = false;
				return false;
			}
			var content = _.reduce( this.findAllRootSorted(), function ( memo, modelArray ) {
				var model = vc.shortcodes.get( modelArray );

				return memo + this.storageCreateShortcodeString( model );
			}, '', this );
			this.setContent( content );
			this.checksum = vc_globalHashCode( content );

			return this;
		},
		/**
		 * If shortcode is container like, gets content of is shortcode in shortcodes style.
		 * @param parent - shortcode inside which content is.
		 * @return {*}
		 * @private
		 */
		_storageGetShortcodeContent: function ( parent ) {
			var models, params;
			models = _.sortBy( _.filter( this.data, function ( model ) {
				// Filter children
				return model.parent_id === parent.get( 'id' );
			} ), function ( model ) {
				// Sort by `order` field
				return model.order;
			} );
			if ( !models.length ) {
				params = _.extend( {}, parent.get( 'params' ) );

				return _.isUndefined( params.content ) ? '' : params.content;
			}

			return _.reduce( models, function ( memo, modelArray ) {
				var model = vc.shortcodes.get( modelArray );
				return memo + this.storageCreateShortcodeString( model );
			}, '', this );
		},
		/**
		 * Get content of main editor of current post. Data is used as models collection of shortcodes.
		 * @return {*}
		 */
		getContent: function () {
			if ( _.isObject( window.tinymce ) && tinymce.editors.content ) {
				tinymce.editors.content.save();
			}
			return window.vc_wpnop( $( '#content' ).val() || '' );
		},
		addUndo: _.debounce( function ( content ) {
			if ( vc.undoRedoApi ) {
				vc.undoRedoApi.add( content );
			}
		}, 100 ),
		/**
		 * Set content of the current_post inside editor.
		 * @param content
		 * @private
		 */
		setContent: function ( content ) {
			this.addUndo( content );
			var contentTinyMce = window.tinyMCE && window.tinyMCE.get && window.tinyMCE.get( 'content' );
			content = vc_wpautop( content );
			if (!this.isChanged) {
				window.jQuery( window ).on( 'beforeunload.vcSave', function () {
					return window.i18nLocale.confirm_to_leave;
				} );
			}
			this.isChanged = true;
			$( '#content' ).val( content );
			if ( contentTinyMce && contentTinyMce.setContent ) {
				contentTinyMce.setContent( content );
				contentTinyMce.fire( 'change' );
			}
		},
		/**
		 * Parse shortcode string into objects.
		 * @param data
		 * @param content
		 * @param parent
		 * @return {*}
		 */
		parseContent: function ( data, content, parent ) {
			var tags = _.keys( vc.map ).join( '|' ),
				reg = window.wp.shortcode.regexp( tags ),
				matches = content.trim().match( reg );
			if ( _.isNull( matches ) ) {
				return data;
			}
			_.each( matches, function ( raw ) {
				var sub_matches = raw.match( this.regexp( tags ) ),
					sub_content = sub_matches[ 5 ],
					sub_regexp = new RegExp( '^[\\s]*\\[\\[?(' + _.keys( vc.map ).join( '|' ) + ')(?![\\w-])' ),
					id = window.vc_guid(),
					atts_raw = window.wp.shortcode.attrs( sub_matches[ 3 ] ),
					atts = {},
					shortcode,
					map_settings;
				_.each( atts_raw.named, function ( value, key ) {
					atts[ key ] = this.unescapeParam( value );
				}, this );
				shortcode = {
					id: id,
					shortcode: sub_matches[ 2 ],
					order: this.order,
					params: _.extend( {}, atts ),
					parent_id: (_.isObject( parent ) ? parent.id : false),
					root_id: (_.isObject( parent ) ? parent.root_id : id)
				};
				map_settings = vc.map[ shortcode.shortcode ];
				this.order += 1;
				if ( _.isArray( data ) ) {
					data.push( shortcode );
					id = data.length - 1;
				} else {
					data[ id ] = shortcode;
				}
				if ( id == shortcode.root_id ) {
					data[ id ].html = raw;
				}
				if ( _.isString( sub_content ) && sub_content.match( sub_regexp ) &&
					(
						(_.isBoolean( map_settings.is_container ) && true === map_settings.is_container) ||
						(!_.isEmpty( map_settings.as_parent ) && false !== map_settings.as_parent)
					) ) {
					data = this.parseContent( data, sub_content, data[ id ] );
				} else if ( _.isString( sub_content ) && sub_content.length && 'vc_row' === sub_matches[ 2 ] ) {
					data = this.parseContent( data,
						'[vc_column width="1/1"][vc_column_text]' + sub_content + '[/vc_column_text][/vc_column]',
						data[ id ] );
				} else if ( _.isString( sub_content ) && sub_content.length && 'vc_column' === sub_matches[ 2 ] ) {
					data = this.parseContent( data,
						'[vc_column_text]' + sub_content + '[/vc_column_text]',
						data[ id ] );
				} else if ( _.isString( sub_content ) ) {
					data[ id ].params.content = sub_content;
				}
			}, this );
			return data;
		},
		/**
		 * Checks by checksum is content changed.
		 * @return {Boolean}
		 */
		isContentChanged: function () {
			return false === this.checksum || this.checksum !== vc_globalHashCode( this.getContent() );
		},
		/**
		 * Wrap content which is not inside vc shorcodes.
		 * @param content
		 * @return {*}
		 */
		wrapData: function ( content ) {
			var tags = _.keys( vc.map ).join( '|' ),
				reg = this.regexp_split( 'vc_row' ),
				starts_with_shortcode = new RegExp( '^\\[(\\[?)(' + tags + ')', 'g' );
			// hacks: vc_section
			var _this = this;

			var storage = {};
			var i = 0;
			content = wp.shortcode.replace( 'vc_section', content, function ( data ) {
				var toSave = {
					attrs: data.attrs.named,
					content: _this.wrapData( data.content )
				};
				i ++;
				var hash = 'vc_pseudo_section_' + i + '_' + VCS4() + VCS4();
				storage[ hash ] = {
					tag: hash,
					data: toSave
				};
				return '[vc_row][vc_pseudo_section id="' + hash + '"][/vc_pseudo_section][/vc_row]';
			} );

			var matches = _.filter( content.trim().split( reg ), function ( value ) {
				if ( !_.isEmpty( value ) ) {
					return value;
				}
			} );
			content = _.reduce( matches, function ( mem, value ) {
				if ( value.trim().indexOf(
					'vc_pseudo_section_' ) === - 1 && !value.trim().match( starts_with_shortcode ) ) {
					value = '[vc_row][vc_column][vc_column_text]' + value + '[/vc_column_text][/vc_column][/vc_row]';
				}
				var matches_local = value.match( vc_regexp_shortcode() );
				/**
				 * Wrap existed shortcodes that is not containers (why not container too? because VC_ROW!)
				 */
				if ( _.isArray( matches_local ) && !_.isUndefined( matches_local[ 2 ] ) && matches_local[ 2 ].indexOf(
					'vc_pseudo_section_' ) === - 1 && !_.isUndefined( vc.map[ matches_local[ 2 ] ] ) ) {
					if ( (_.isUndefined( vc.map[ matches_local[ 2 ] ].is_container ) || !vc.map[ matches_local[ 2 ] ].is_container) && _.isEmpty(
						vc.map[ matches_local[ 2 ] ].as_parent ) ) {
						value = '[vc_row][vc_column]' + value + '[/vc_column][/vc_row]';
					}
				}

				return mem + value;
			}, '' );

			// Re wrap back vc_section!
			if ( Object.keys( storage ).length > 0 ) {
				content = content.replace( /\[vc_row\]\[vc_pseudo_section/g, '[vc_pseudo_section' );
				content = content.replace( /\[\/vc_pseudo_section\]\[\/vc_row\]/g, '[/vc_pseudo_section]' );
				content = wp.shortcode.replace( 'vc_pseudo_section', content, function ( data ) {
					var item = storage[ data.attrs.named.id ];
					return wp.shortcode.string( {
						tag: 'vc_section',
						attrs: item.data.attrs,
						content: item.data.content
					} );
				} );
			}

			return content;
		},
		/**
		 * Get data from hidden field and parse it from string to objects list.
		 * @return {*}
		 */
		fetch: function () {
			if ( !this.isContentChanged() ) {
				return this;
			}
			this.order = 0;
			var content = this.getContent();
			this.checksum = vc_globalHashCode( content );
			content = this.wrapData( content );
			this.data = this.parseContent( {}, content );
		},
		/**
		 * Append new data to existing one.
		 * @param content - string of shortcodes.
		 */
		append: function ( content ) {
			this.data = {};
			this.order = 0;
			try {
				var current_content = this.getContent();
				this.setContent( current_content + "" + content );
			} catch ( e ) {
				if ( window.console && window.console.warn ) {
					window.console.warn( 'storage.append error', e );
				}
			}
		},
		/**
		 * Regexp used to split unwrapped data.
		 */
		regexp_split: _.memoize( function ( tags ) {
			return new RegExp( '(\\[(\\[?)[' + tags + ']+' +
				'(?![\\w-])' +
				'[^\\]\\/]*' +
				'[\\/' +
				'(?!\\])' +
				'[^\\]\\/]*' +
				']?' +
				'(?:' +
				'\\/]' +
				'\\]|\\]' +
				'(?:' +
				'[^\\[]*' +
				'(?:\\[' +
				'(?!\\/' + tags + '\\])[^\\[]*' +
				')*' +
				'' +
				'\\[\\/' + tags + '\\]' +
				')?' +
				')' +
				'\\]?)', 'g' );
		} ),
		regexp: _.memoize( function ( tags ) {
			return new RegExp( '\\[(\\[?)(' + tags + ')(?![\\w-])([^\\]\\/]*(?:\\/(?!\\])[^\\]\\/]*)*?)(?:(\\/)\\]|\\](?:([^\\[]*(?:\\[(?!\\/\\2\\])[^\\[]*)*)(\\[\\/\\2\\]))?)(\\]?)' );
		} )
	};
	vc.storage = new vc.Storage();

})( window.jQuery );