prefix}icl_translations` AS trans1
INNER JOIN `{$wpdb->prefix}icl_translations` AS trans2 ON (trans2.trid = trans1.trid)
WHERE trans1.element_id='%d' AND trans2.source_language_code IS NULL
SQL;
	    $sqlQueryPrepared = $wpdb->prepare($sqlQuery, array($postId));
        $mainLanguagePostId = $wpdb->get_var($sqlQueryPrepared);
	    $type = apply_filters( 'wpml_element_type', get_post_type( $mainLanguagePostId ) );
	    $trid = apply_filters( 'wpml_element_trid', false, $mainLanguagePostId, $type );
	    return apply_filters( 'wpml_get_element_translations', array(), $trid, $type );
    }
    /**
     * Save post metadata when a post is saved (not for the "Latest Blog Posts" home page type)
     * Only for post type
     *
     * Dashboard view: triggered via hook
     * Front-end view: triggered by direct call
     *
     * @param $postId
     * @param mixed $post
     */
    public function savePost($postId, $post = '')
    {
	    if (empty($post) || $post === '') {
		    global $post;
	    }
	    if ( ! isset( $post->ID, $post->post_type ) ) {
		    return;
	    }
	    // Has to be a public post type
	    $obj = get_post_type_object($post->post_type);
	    if ( ! isset($obj->public) || $obj->public < 1 ) {
		    return;
	    }
	    // only for admins
	    if (! Menu::userCanManageAssets()) {
		    return;
	    }
	    // Any page options set? From the Side Meta Box "Asset CleanUp: Options"
	    // Could be just these fields available in the form (e.g. unavailable CSS/JS manager due to the page set to not load the plugin at all)
	    $this->updatePageOptions($post->ID);
	    // This is triggered only if the "Asset CleanUp" meta box was loaded with the list of assets (either in edit post/page or in "CSS & JS Manager" -> "Manage CSS/JS")
	    // Otherwise, $_POST[WPACU_PLUGIN_ID] will be taken as empty which might be not if there are values in the database
    	if (! Misc::getVar('post', 'wpacu_unload_assets_area_loaded')) {
    	    return;
	    }
        $wpacuNoLoadAssets = Misc::getVar('post', WPACU_PLUGIN_ID, array());
        if (is_array($wpacuNoLoadAssets)) {
            global $wpdb;
            $noUpdate = false;
            // Is the list empty?
            if (empty($wpacuNoLoadAssets)) {
                // Remove any row with no results
                $wpdb->delete(
                    $wpdb->postmeta,
                    array('post_id' => $postId, 'meta_key' => '_' . WPACU_PLUGIN_ID . '_no_load')
                );
                $noUpdate = true;
            }
            if (! $noUpdate) {
                $jsonNoAssetsLoadList = wp_json_encode($wpacuNoLoadAssets);
	            if (! add_post_meta($postId, '_' . WPACU_PLUGIN_ID . '_no_load', $jsonNoAssetsLoadList, true)) {
                    update_post_meta($postId, '_' . WPACU_PLUGIN_ID . '_no_load', $jsonNoAssetsLoadList);
                }
            }
        }
        // Was the Assets List Layout changed?
	    self::updateAssetListLayoutSettings();
        // If globally disabled, make an exception to load for submitted assets
        $this->saveLoadExceptions('post', $postId);
        $this->saveLoadExceptionsPostType($post->post_type);
	    // Add / Remove Site-wide Unloads
	    $this->updateEverywhereUnloads();
        // Any bulk unloads or removed? (e.g. all pages of a certain post type)
	    $this->saveToBulkUnloads($post);
	    $this->removeBulkUnloads($post->post_type);
        // Any preloads
	    Preloads::updatePreloads();
	    // Any handle notes
	    self::updateHandleNotes();
	    // Any always load it if user is logged in?
	    self::saveGlobalLoadExceptions();
	    // Any ignore deps
	    self::updateIgnoreChild();
	    add_action('wpacu_admin_notices', array($this, 'pageUpdated'));
	    self::clearTransients();
	    // In case Combine CSS/JS was enabled and there are traces of JSON files in the caching directory
        // Clear them if the caching timing expired as they are not relevant anymore and reduce the disk's space
	    OptimizeCommon::clearJsonStorageForPost($postId, true);
        self::afterPostUpdate($postId);
	    // Note: Cache is cleared (except the JSON files related to CSS/JS combine option) after the post/page is updated via a separate AJAX call
	    // To avoid the usage of too much memory (good for shared environments) and avoid any memory related errors showing up to the user which could be confusing
    }
	/**
     * This is to update the permalink for the post in "Page Options" if the following option was ever used for the post: "Do not load Asset CleanUp Pro on this page (this will disable any functionality of the plugin)"
     * This takes action when the CSS/JS manager is updated for a specific post (e.g. post, page, attachment, custom post type)
     *
	 * @param $postId
	 */
	public static function afterPostUpdate($postId)
    {
        global $wpdb;
        // The post might have the following page option: "Do not load Asset CleanUp Pro on this page (this will disable any functionality of the plugin)"
        // If the admin changed the slug, we need to update the page URI as well that is used very early in the triggering of the plugin
        // when get_permalink() is not available (e.g. outside any action hook or in the MU plugin)
	    $pageOptionJson = $wpdb->get_var( 'SELECT meta_value FROM `' . $wpdb->prefix . 'postmeta` WHERE post_id=\''.$postId.'\' && meta_key=\'_'.WPACU_PLUGIN_ID.'_page_options\' && meta_value LIKE \'%no_wpacu_load%\'' );
	    $postPageOptions = @json_decode($pageOptionJson, ARRAY_A);
	    if ( ! isset($postPageOptions['no_wpacu_load']) ) {
	        return;
        }
        $postPageOptions['_page_uri'] = Misc::getPageUri($postId);
        update_post_meta($postId, '_' . WPACU_PLUGIN_ID . '_page_options', wp_json_encode(Misc::filterList($postPageOptions)));
    }
    /**
     * @param $wpacuNoLoadAssets
     */
    public function updateFrontPage($wpacuNoLoadAssets)
    {
	    // Any page options set? From the Side Meta Box "Asset CleanUp: Options"
	    // Could be just these fields available in the form (e.g. unavailable CSS/JS manager due to the page set to not load the plugin at all)
	    $this->updatePageOptions(0, 'front_page');
	    // Needed in case the user clicks "Update" on a page without assets retrieved
	    // Avoid resetting the existing values
	    if (! Misc::getVar('post', 'wpacu_unload_assets_area_loaded')) {
		    return;
	    }
	    if (! is_array($wpacuNoLoadAssets)) {
            return; // only arrays (empty or not) should be used
        }
	    // Was the Assets List Layout changed?
	    self::updateAssetListLayoutSettings();
        $jsonNoAssetsLoadList = wp_json_encode( $wpacuNoLoadAssets );
	    Misc::addUpdateOption( WPACU_PLUGIN_ID . '_front_page_no_load', $jsonNoAssetsLoadList );
	    // If globally disabled, make an exception to load for submitted assets
        $this->saveLoadExceptions('front_page');
        // Add / Remove Site-wide Unloads
		$this->updateEverywhereUnloads();
	    // Any preloads
	    Preloads::updatePreloads();
		// Any handle notes
        self::updateHandleNotes();
	    // Any always load it if user is logged in?
	    self::saveGlobalLoadExceptions();
        // Any ignore deps
        self::updateIgnoreChild();
	    add_action('wpacu_admin_notices', array($this, 'homePageUpdated'));
        $this->frontEndUpdateFor['homepage'] = true;
	    self::clearTransients();
	    // Clear all cache
	    // Note: The cache is cleared after the page is saved
    }
	/**
	 *
	 */
	public function homePageUpdated()
    {
	?>
	    
            afterSubmitMsg['homepage'],
				    array(
                       'style'  => array(),
                       'class'  => array(),
                       'strong' => array(),
                       'a' => array(
                           'target' => array(),
                           'href'   => array()
                       )
                    )
			    ); ?>
	     
	
        
            afterSubmitMsg['page'],
		            array(
			            'style'  => array(),
			            'class'  => array(),
			            'strong' => array(),
			            'a' => array(
				            'target' => array(),
				            'href'   => array()
			            )
		            )
                ); ?>
         
		
        
            afterSubmitMsg['invalid_nonce_error'],
		            array(
			            'style'  => array(),
			            'class'  => array(),
			            'strong' => array(),
			            'a' => array(
				            'target' => array(),
				            'href'   => array()
			            )
		            )
                ); ?>
         
         array(), 'scripts' => array());
        // [Start] Clear existing list first
        if ($type === 'post') {
            delete_post_meta($postId, '_' . WPACU_PLUGIN_ID . '_load_exceptions');
        } elseif ($type === 'front_page') {
            delete_option( WPACU_PLUGIN_ID . '_front_page_load_exceptions');
        }
	    // [End] Clear existing list first
        // Load Exception
        // On this page or page type such as 404, search, etc.
        foreach (array('styles', 'scripts') as $assetType) {
            $postKey    = ($assetType === 'styles') ? 'wpacu_styles_load_it' : 'wpacu_scripts_load_it';
            $optionsKey = ($assetType === 'styles') ? 'wpacu_options_styles' : 'wpacu_options_scripts';
	        if ( isset( $_POST[$postKey] ) && ! empty( $_POST[$postKey] ) ) {
		        foreach ( $_POST[$postKey] as $wpacuHandle ) {
			        // Do not append it if the global unload is removed
			        if ( isset( $_POST[$optionsKey][ $wpacuHandle ] )
			             && $_POST[$optionsKey][ $wpacuHandle ] === 'remove' ) {
				        continue;
			        }
			        $loadExceptions[$assetType][] = $wpacuHandle;
		        }
	        }
        }
        if (! empty($loadExceptions['styles']) || ! empty($loadExceptions['scripts'])) {
            // Default
            $list =  array('styles' => array(), 'scripts' => array());
            // Build list
            foreach ( array('styles', 'scripts') as $assetType ) {
	            if ( ! empty( $loadExceptions[$assetType] ) ) {
		            foreach ( $loadExceptions[$assetType] as $postHandle ) {
			            $list[$assetType][] = $postHandle;
		            }
	            }
	            if (is_array($list[$assetType])) {
		            $list[$assetType] = array_unique($list[$assetType]);
	            }
            }
            $jsonLoadExceptions = wp_json_encode(Misc::filterList($list));
            if ( $type === 'post' && (! add_post_meta($postId, '_' . WPACU_PLUGIN_ID . '_load_exceptions', $jsonLoadExceptions, true)) ) {
                update_post_meta( $postId, '_' . WPACU_PLUGIN_ID . '_load_exceptions', $jsonLoadExceptions );
            } elseif ($type === 'front_page') {
	            Misc::addUpdateOption( WPACU_PLUGIN_ID . '_front_page_load_exceptions', $jsonLoadExceptions );
            }
        }
    }
	/**
	 *
	 */
	public function saveLoadExceptionsPostType($wpacuPostType)
    {
	    // On all pages belonging to a (custom) post type (e.g. WooCommerce product page)
	    $referenceKey = WPACU_FORM_ASSETS_POST_KEY;
	    $loadExceptions = array('styles' => array(), 'scripts' => array());
	    // From v1.2.0.5
        if (isset($_POST[$referenceKey]['styles']) || isset($_POST[$referenceKey]['scripts'])) {
            foreach (array('styles', 'scripts') as $assetType) {
	            if ( isset( $_POST[ $referenceKey ][$assetType] ) && ! empty( $_POST[ $referenceKey ][$assetType] ) ) {
		            foreach ( $_POST[ $referenceKey ][$assetType] as $assetHandle => $values ) {
			            $assetValue = isset( $values['load_it_post_type'] ) && $values['load_it_post_type'] ? $values['load_it_post_type'] : ''; // '1' or ''
			            $loadExceptions[$assetType][ $assetHandle ] = $assetValue;
		            }
	            }
            }
        } else {
	        // Prior to v1.2.0.5
	        foreach (array('styles', 'scripts') as $assetType) {
	            $indexKey = 'wpacu_'.$assetType.'_load_it_post_type';
		        if ( isset( $_POST[$indexKey] ) && ! empty( $_POST[$indexKey] ) ) {
			        $wpacuPostType = key( $_POST[$indexKey] );
			        $loadExceptions[$assetType] = $_POST[$indexKey][ $wpacuPostType ];
		        }
	        }
        }
	    if ((! empty($loadExceptions['styles']) || ! empty($loadExceptions['scripts'])) && (isset($wpacuPostType) && $wpacuPostType)) {
		    // Default
		    $listToSave = array( 'styles' => array(), 'scripts' => array() );
		    // Build list
		    foreach (array('styles', 'scripts') as $assetType) {
		        $listToSave[$assetType] = ( ! empty( $loadExceptions[$assetType] ) ) ? $loadExceptions[$assetType] : array();
		    }
		    $jsonLoadExceptionsToAdd = wp_json_encode(array($wpacuPostType => $listToSave));
		    $optionToUpdate = WPACU_PLUGIN_ID . '_post_type_load_exceptions';
		    $existingListEmpty = array( $wpacuPostType => array( 'styles' => array(), 'scripts' => array() ) );
		    $existingListJson = get_option($optionToUpdate);
		    $existingListData = Main::instance()->existingList($existingListJson, $existingListEmpty);
		    $existingList = $existingListData['list'];
		    if ( $existingListJson && is_array($existingList) && ! empty($existingList) ) {
                if (isset($existingList[$wpacuPostType])) {
                    foreach ($listToSave as $assetType => $assetValues) {
                        foreach ($assetValues as $assetHandle => $assetValue) {
	                        $existingList[ $wpacuPostType ][ $assetType ][ $assetHandle ] = $assetValue;
                        }
                    }
                } else {
                    $existingList[$wpacuPostType] = $listToSave;
                }
                // Clear empty (redundant) values
			    foreach ($existingList as $wpacuPostTypeDb => $assetTypes) {
				    foreach ($assetTypes as $assetType => $assetValues) {
				        if (empty($assetValues)) {
				            unset($existingList[$wpacuPostTypeDb][$assetType]);
				        }
				        foreach ($assetValues as $assetHandle => $assetValue) {
					        if ( $assetValue === '' ) {
						        unset( $existingList[ $wpacuPostTypeDb ][ $assetType ][ $assetHandle ] );
					        }
					        if (empty($existingList[ $wpacuPostTypeDb ][ $assetType ])) {
						        unset( $existingList[$wpacuPostTypeDb][$assetType] );
					        }
					        if (empty($existingList[$wpacuPostTypeDb])) {
						        unset($existingList[$wpacuPostTypeDb]);
					        }
				        }
				    }
			    }
			    Misc::addUpdateOption( $optionToUpdate, wp_json_encode($existingList) );
		    } else {
			    Misc::addUpdateOption( $optionToUpdate, $jsonLoadExceptionsToAdd );
		    }
	    }
    }
	/**
	 * e.g. Always load the handle (if unloaded by any rule) if the user is logged-in (applies site-wide)
	 */
	public static function saveGlobalLoadExceptions()
    {
	    $optionToUpdate  = WPACU_PLUGIN_ID . '_global_data';
	    $formTargetKey   = 'wpacu_load_it_logged_in';
	    $targetGlobalKey = 'load_it_logged_in';
	    $referenceKey = WPACU_FORM_ASSETS_POST_KEY;
	    if (! Misc::isValidRequest('post', $referenceKey)) {
		    return;
	    }
	    if (! isset($_POST[$referenceKey]['styles']) && ! isset($_POST[$referenceKey]['scripts'])) {
		    return;
	    }
	    $existingListEmpty = array('styles' => array($targetGlobalKey => array()), 'scripts' => array($targetGlobalKey => array()));
	    $existingListJson = get_option($optionToUpdate);
	    $existingListData = Main::instance()->existingList($existingListJson, $existingListEmpty);
	    $existingList = $existingListData['list'];
	    foreach (array('styles', 'scripts') as $assetType) {
		    if ( isset( $_POST[ $referenceKey ][$assetType] ) && ! empty( $_POST[ $referenceKey ][$assetType] ) ) {
			    foreach ( array_keys( $_POST[ $referenceKey ][$assetType] ) as $assetHandle ) {
			        // The checkbox was ticked (it's not empty)
				    $isSelected = isset( $_POST[$formTargetKey][$assetType][ $assetHandle ] ) && $_POST[$formTargetKey][$assetType][ $assetHandle ];
				    if ( $isSelected ) {
					    $existingList[$assetType][ $targetGlobalKey ][ $assetHandle ] = 1;
				    } else {
					    unset( $existingList[$assetType][ $targetGlobalKey ][ $assetHandle ] );
					    // Are there no values left? Remove the empty array (free space)
					    if (empty($existingList[$assetType][ $targetGlobalKey ])) {
					    	unset($existingList[$assetType][ $targetGlobalKey ]);
					    }
				    }
			    }
		    }
	    }
	    Misc::addUpdateOption($optionToUpdate, wp_json_encode(Misc::filterList($existingList)));
    }
	/**
     * This method should ONLY be triggered when the "Asset CleanUp: Options" area is visible
     *
	 * @param $postId
	 * @param string $type
	 */
	public function updatePageOptions($postId, $type = 'post')
	{
		// Is the "Asset CleanUp: Page Options" meta box not loaded?
		// Then do not perform any update below
		if ( ! Misc::getVar( 'post', 'wpacu_page_options_area_loaded', false ) ) {
			return;
		}
		$pageOptions = Misc::getVar( 'post', WPACU_PLUGIN_ID . '_page_options', array() );
	    if ($type === 'post' || $postId > 0) {
		    /*
			 * For posts, pages, custom post types
			 */
		    // No page options? Delete any entry from the database to free up space
		    // instead of updating it as an empty entry
		    if ( empty( $pageOptions ) ) {
			    delete_post_meta( $postId, '_' . WPACU_PLUGIN_ID . '_page_options' );
			    return;
		    }
		    // Save the page URI as it's needed instead of get_permalink() that can't be called too early (e.g. outside an action hook or in a MU plugin)
		    $pageOptions['_page_uri'] = Misc::getPageUri($postId);
		    $pageOptionsJson = wp_json_encode( Misc::filterList($pageOptions) );
		    if ( ! add_post_meta( $postId, '_' . WPACU_PLUGIN_ID . '_page_options', $pageOptionsJson, true ) ) {
			    update_post_meta( $postId, '_' . WPACU_PLUGIN_ID . '_page_options', $pageOptionsJson );
		    }
	    } elseif ($type === 'front_page') {
            /*
             * For the homepage (e.g. the latest posts), but not a page set as homepage
             */
		    $existingListJson = get_option(WPACU_PLUGIN_ID . '_global_data');
		    $existingListData = Main::instance()->existingList($existingListJson, array());
		    $existingList = $existingListData['list'];
		    $existingList['page_options']['homepage'] = $pageOptions;
		    Misc::addUpdateOption(WPACU_PLUGIN_ID . '_global_data', wp_json_encode(Misc::filterList($existingList)));
	    }
	}
	/**
	 * Triggers either "saveToEverywhereUnloads" or "removeEverywhereUnloads" methods
	 */
	public function updateEverywhereUnloads()
    {
	    /*
	     * Any global (all pages / everywhere) UNLOADS?
	     * Coming from a POST request
	     */
	    $reqStyles  = Misc::getVar('post', 'wpacu_global_unload_styles', array());
	    $reqScripts = Misc::getVar('post', 'wpacu_global_unload_scripts', array());
	    $this->saveToEverywhereUnloads($reqStyles, $reqScripts);
	    /*
	     * Any global (all pages / everywhere) REMOVED?
	     * Coming from a POST request
	     */
	    $this->removeEverywhereUnloads(array(), array(), 'post');
    }
	/**
	 * @param array $reqStyles
	 * @param array $reqScripts
	 */
	public function saveToEverywhereUnloads($reqStyles = array(), $reqScripts = array())
    {
        // Is there any entry already in JSON format?
        $existingListJson = get_option(WPACU_PLUGIN_ID . '_global_unload');
        // Default list as array
        $existingListEmpty = array('styles' => array(), 'scripts' => array());
	    $existingListData = Main::instance()->existingList($existingListJson, $existingListEmpty);
	    $existingList = $existingListData['list'];
        // Append to the list anything from the POST (if any)
        if (! empty($reqStyles)) {
            foreach ($reqStyles as $reqStyleHandle) {
                $existingList['styles'][] = $reqStyleHandle;
            }
        }
        if (! empty($reqScripts)) {
            foreach ($reqScripts as $reqScriptHandle) {
                $existingList['scripts'][] = $reqScriptHandle;
            }
        }
        // Make sure all entries are unique (no handle duplicates)
        foreach (array('styles', 'scripts') as $assetType) {
	        if ( isset( $existingList[$assetType] ) && is_array( $existingList[$assetType] ) ) {
		        $existingList[$assetType] = array_unique( $existingList[$assetType] );
	        }
        }
        Misc::addUpdateOption(WPACU_PLUGIN_ID . '_global_unload', wp_json_encode(Misc::filterList($existingList)));
    }
	/**
	 * @param array $stylesList
	 * @param array $scriptsList
	 * @param string $checkType
	 *
	 * @return bool
	 */
	public function removeEverywhereUnloads($stylesList = array(), $scriptsList = array(), $checkType = '')
    {
    	if ($checkType === 'post') {
		    $stylesList  = Misc::getVar('post', 'wpacu_options_styles', array());
		    $scriptsList = Misc::getVar('post', 'wpacu_options_scripts', array());
	    }
        $removeStylesList = $removeScriptsList = array();
        $isUpdated = false;
        if (! empty($stylesList)) {
            foreach ($stylesList as $handle => $action) {
                if ($action === 'remove') {
                    $removeStylesList[] = $handle;
                }
            }
        }
        if (! empty($scriptsList)) {
            foreach ($scriptsList as $handle => $action) {
                if ($action === 'remove') {
                    $removeScriptsList[] = $handle;
                }
            }
        }
        $existingListJson = get_option(WPACU_PLUGIN_ID . '_global_unload');
        if (! $existingListJson) {
            return false;
        }
        $existingList = json_decode($existingListJson, true);
        if (Misc::jsonLastError() === JSON_ERROR_NONE) {
            foreach (array('styles', 'scripts') as $assetType) {
                if ($assetType === 'styles') {
                    $list = $removeStylesList;
                } elseif ($assetType === 'scripts') {
                    $list = $removeScriptsList;
                }
                if (empty($list)) {
                    continue;
                }
                foreach ($list as $handle) {
                    $handleKey = isset($existingList[$assetType]) ? array_search($handle, $existingList[$assetType]) : false;
                    if ($handleKey !== false) {
                        unset($existingList[$assetType][$handleKey]);
                        $isUpdated = true;
                    }
                }
            }
            if ($isUpdated) {
                Misc::addUpdateOption(WPACU_PLUGIN_ID . '_global_unload', wp_json_encode(Misc::filterList($existingList)));
            }
        }
        return $isUpdated;
    }
	/**
	 * @param string $post
	 */
	public function saveToBulkUnloads($post = '')
    {
        if ($post === '') {
	        global $post;
        }
	    $postType = isset( $post->post_type ) ? $post->post_type : false;
	    // Free Version: It only deals with 'post_type' bulk unloads
	    if ( ! $postType ) {
		    return;
	    }
        $postStyles  = Misc::getVar('post', 'wpacu_bulk_unload_styles', array());
        $postScripts = Misc::getVar('post', 'wpacu_bulk_unload_scripts', array());
        // Is there any entry already in JSON format?
        $existingListJson = get_option( WPACU_PLUGIN_ID . '_bulk_unload');
        // Default list as array
        $existingListEmpty = array(
            'styles'  => array('post_type' => array($postType => array())),
            'scripts' => array('post_type' => array($postType => array()))
        );
	    $existingListData = Main::instance()->existingList($existingListJson, $existingListEmpty);
	    $existingList = $existingListData['list'];
        // Append to the list anything from the POST (if any)
        // Make sure all entries are unique (no handle duplicates)
        $list = array();
        foreach (array('styles', 'scripts') as $assetType) {
            if ($assetType === 'styles') {
                $list = $postStyles;
            } elseif ($assetType === 'scripts') {
                $list = $postScripts;
            }
            if (empty($list)) {
                continue;
            }
            foreach ($list as $bulkType => $values) {
                if (empty($values)) {
                    continue;
                }
                if ($bulkType === 'post_type') {
                    foreach ($values as $postType => $handles) {
                        if (empty($handles)) {
                            continue;
                        }
                    	foreach (array_unique($handles) as $handle) {
		                    $existingList[ $assetType ]['post_type'][ $postType ][] = $handle;
	                    }
	                    $existingList[ $assetType ]['post_type'][ $postType ] = array_unique($existingList[ $assetType ]['post_type'][ $postType ]);
                    }
                }
            }
        }
	    Misc::addUpdateOption( WPACU_PLUGIN_ID . '_bulk_unload', wp_json_encode(Misc::filterList($existingList)));
    }
    /**
     * Lite Version: For post, pages, custom post types
     * @param mixed $postType
     * @return bool
     */
    public function removeBulkUnloads($postType = '')
    {
        if (! $postType) {
            global $post;
            // In the LITE version, post type unload is the only option for bulk unloads
            // $postType could be 'post', 'page' or a custom post type such as 'product' (WooCommerce), 'download' (Easy Digital Downloads), etc.
	        $postType = isset($post->post_type) ? $post->post_type : false;
            if (! $postType) {
            	return false;
            }
        }
	    $bulkType = 'post_type';
	    $stylesList = Misc::getVar('post', 'wpacu_options_'.$bulkType.'_styles', array());
	    $scriptsList = Misc::getVar('post', 'wpacu_options_'.$bulkType.'_scripts', array());
        if (empty($stylesList) && empty($scriptsList)) {
        	return false;
        }
        $removeStylesList = $removeScriptsList = array();
        $isUpdated = false;
        if (! empty($stylesList)) {
            foreach ($stylesList as $handle => $action) {
                if ($action === 'remove') {
                    $removeStylesList[] = $handle;
                }
            }
        }
        if (! empty($scriptsList)) {
            foreach ($scriptsList as $handle => $action) {
                if ($action === 'remove') {
                    $removeScriptsList[] = $handle;
                }
            }
        }
        $existingListJson = get_option( WPACU_PLUGIN_ID . '_bulk_unload');
        if (! $existingListJson) {
            return false;
        }
        $existingList = json_decode($existingListJson, true);
        if (Misc::jsonLastError() === JSON_ERROR_NONE) {
            $list = array();
            foreach (array('styles', 'scripts') as $assetType) {
                if ($assetType === 'styles') {
                    $list = $removeStylesList;
                } elseif ($assetType === 'scripts') {
                    $list = $removeScriptsList;
                }
                if (empty($list)) {
                    continue;
                }
	            foreach ( $existingList[ $assetType ][ $bulkType ][ $postType ] as $handleKey => $handle ) {
		            if ( in_array( $handle, $list ) ) {
			            unset( $existingList[ $assetType ][ $bulkType ][ $postType ][ $handleKey ] );
			            $isUpdated = true;
		            }
	            }
            }
	        Misc::addUpdateOption(WPACU_PLUGIN_ID . '_bulk_unload', wp_json_encode(Misc::filterList($existingList)));
        }
        return $isUpdated;
    }
	/**
	 *
	 */
	public static function updateHandleNotes()
    {
        if (! Misc::isValidRequest('post', 'wpacu_handle_notes')) {
            return;
        }
        if (! isset($_POST['wpacu_handle_notes']['styles']) && ! isset($_POST['wpacu_handle_notes']['scripts'])) {
            return;
        }
	    $optionToUpdate = WPACU_PLUGIN_ID . '_global_data';
	    $globalKey = 'notes';
	    $existingListEmpty = array('styles' => array($globalKey => array()), 'scripts' => array($globalKey => array()));
	    $existingListJson = get_option($optionToUpdate);
	    $existingListData = Main::instance()->existingList($existingListJson, $existingListEmpty);
	    $existingList = $existingListData['list'];
	    foreach (array('styles', 'scripts') as $assetType) {
		    if ( isset( $_POST['wpacu_handle_notes'][$assetType] ) && ! empty( $_POST['wpacu_handle_notes'][$assetType] ) ) {
			    foreach ( $_POST['wpacu_handle_notes'][$assetType] as $assetHandle => $assetNote ) {
				    $assetNote = stripslashes( $assetNote );
				    if ( $assetNote === '' && isset( $existingList[$assetType][ $globalKey ][ $assetHandle ] ) ) {
					    unset( $existingList[$assetType][ $globalKey ][ $assetHandle ] );
				    } elseif ( $assetNote !== '' ) {
					    $existingList[$assetType][ $globalKey ][ $assetHandle ] = $assetNote;
				    }
			    }
		    }
	    }
	    Misc::addUpdateOption($optionToUpdate, wp_json_encode(Misc::filterList($existingList)));
    }
	/**
	 * @param array $mainVarToUse
	 */
	public static function updateIgnoreChild($mainVarToUse = array())
	{
		// No $mainVarToUse passed? Then it's a $_POST
		// Check if $_POST is empty via Misc::isValidRequest()
		$useGlobalPost = false;
		if (empty($mainVarToUse)) {
		    if ( (isset($_POST[WPACU_FORM_ASSETS_POST_KEY]['styles']) && ! empty($_POST[WPACU_FORM_ASSETS_POST_KEY]['styles']))
                || (isset($_POST[WPACU_FORM_ASSETS_POST_KEY]['scripts']) && ! empty($_POST[WPACU_FORM_ASSETS_POST_KEY]['scripts'])) ) {
			    $mainVarToUse = self::updateIgnoreChildAdapt($_POST[WPACU_FORM_ASSETS_POST_KEY]); // New form fields (starting from v1.1.9.9)
		    } elseif (Misc::isValidRequest('post', 'wpacu_ignore_child')) {
			    $useGlobalPost = true;
			} else {
		        return;
		    }
		}
		if (! $useGlobalPost && isset($mainVarToUse['wpacu_ignore_child'])) {
			$bucketToUse = $mainVarToUse['wpacu_ignore_child'];
		} else if (isset($_POST['wpacu_ignore_child'])) {
			$bucketToUse = $_POST['wpacu_ignore_child'];
		}
		if (! isset($bucketToUse['styles']) && ! isset($bucketToUse['scripts'])) {
			return;
		}
		$optionToUpdate = WPACU_PLUGIN_ID . '_global_data';
		$globalKey = 'ignore_child';
		$existingListEmpty = array('styles' => array($globalKey => array()), 'scripts' => array($globalKey => array()));
		$existingListJson = get_option($optionToUpdate);
		$existingListData = Main::instance()->existingList($existingListJson, $existingListEmpty);
		$existingList = $existingListData['list'];
		foreach (array('styles','scripts') as $assetType) {
			if ( isset( $bucketToUse[$assetType] ) && ! empty( $bucketToUse[$assetType] ) ) {
				foreach ( $bucketToUse[$assetType] as $assetHandle => $assetVal ) {
					$assetVal = trim( $assetVal );
					if ( $assetVal === '' && isset( $existingList[$assetType][ $globalKey ][ $assetHandle ] ) ) {
						unset( $existingList[$assetType][ $globalKey ][ $assetHandle ] );
					} elseif ( $assetVal !== '' ) {
						$existingList[$assetType][ $globalKey ][ $assetHandle ] = $assetVal;
					}
				}
			}
		}
		Misc::addUpdateOption($optionToUpdate, wp_json_encode(Misc::filterList($existingList)));
	}
	/**
	 * @param $mainFormArray
	 *
	 * @return array
	 */
	public static function updateIgnoreChildAdapt($mainFormArray)
    {
	    $wpacuIgnoreChildList = array();
        foreach (array('styles', 'scripts') as $assetKey) {
            if (isset($mainFormArray[$assetKey]) && ! empty($mainFormArray[$assetKey])) {
                foreach ($mainFormArray[$assetKey] as $assetHandle => $assetData) {
	                $wpacuIgnoreChildList['wpacu_ignore_child'][$assetKey][$assetHandle] = ''; // default
                    if (isset($assetData['ignore_child']) && $assetData['ignore_child']) {
	                    $wpacuIgnoreChildList['wpacu_ignore_child'][ $assetKey ][ $assetHandle ] = 1;
                    }
                }
            }
        }
        return $wpacuIgnoreChildList;
	}
	/**
     * This function is called via AJAX whenever "+" or "-" is used on an asset's row
     *
	 * @param $newState
	 * @param $handle
	 * @param $handleFor
	 *
	 * @return array|false
	 */
	public static function updateHandleRowStatus($newState, $handle, $handleFor)
	{
		$optionToUpdate = WPACU_PLUGIN_ID . '_global_data';
		$globalKey = 'handle_row_contracted'; // Contracted or Expanded (default)
		$existingListEmpty = array('styles' => array($globalKey => array()), 'scripts' => array($globalKey => array()));
        $existingListJson = get_option($optionToUpdate);
		$existingListData = Main::instance()->existingList($existingListJson, $existingListEmpty);
		$existingList = $existingListData['list'];
		if ($handleFor === 'style') {
		    $keyList = 'styles';
		} elseif ($handleFor === 'script') {
		    $keyList = 'scripts';
		} else {
		    return false;
        }
        // The database value should be equal with '1' suggesting it's contracted (no value means it's expanded by default)
        if ( $newState === 'expanded' && isset( $existingList[$keyList][ $globalKey ][ $handle ] ) ) {
            unset( $existingList[$keyList][ $globalKey ][ $handle ] ); // "expanded" (default)
        } elseif ( $newState === 'contracted' ) {
            $existingList[$keyList][ $globalKey ][ $handle ] = 1; // "contracted"
        }
		Misc::addUpdateOption($optionToUpdate, wp_json_encode(Misc::filterList($existingList)));
        $toReturn = array();
        if (isset($existingList['styles'][$globalKey])) {
	        $toReturn['styles'] = $existingList['styles'][$globalKey];
        }
		if (isset($existingList['scripts'][$globalKey])) {
			$toReturn['scripts'] = $existingList['scripts'][$globalKey];
        }
        return $toReturn;
	}
	/**
     * This is triggered automatically and sets a transient with the handles info
     * It doesn't require any manual action from the user
     *
	 * @param $assetList
	 */
	public static function updateHandlesInfo($assetList)
	{
		$optionToUpdate = WPACU_PLUGIN_ID . '_global_data';
		$globalKey = 'assets_info';
		$existingListEmpty = array('styles' => array($globalKey => array()), 'scripts' => array($globalKey => array()));
		$existingListJson = get_option($optionToUpdate);
		$existingListData = Main::instance()->existingList($existingListJson, $existingListEmpty);
		$existingList = $existingListData['list'];
		// $assetKey could be 'styles' or 'scripts'
		foreach ($assetList as $assetKey => $assetDataHandleList) {
			if (empty($assetDataHandleList) || ! in_array($assetKey, array('styles', 'scripts'))) {
				continue;
			}
			foreach ($assetDataHandleList as $assetObj) {
				$assetArray = (array)$assetObj;
				$assetHandle = $assetArray['handle'];
				// Strip other unused information including the 'handle' (no need to have it twice as it's already in one of the array's keys)
				unset( $assetArray['handle'], $assetArray['textdomain'], $assetArray['translations_path'] );
				// Some handles don't have a "src" value such as "woocommerce-inline"
				if (isset($assetArray['src']) && $assetArray['src']) {
					$assetArray['src'] = Misc::assetFromHrefToRelativeUri( $assetArray['src'], $assetKey );
				}
				// [wpacu_pro]
				if (isset($assetArray['output'])) { // hardcoded assets have an 'output' value
					// Is there already an entry for the same handle with a value set for 'output' and 'output_min'
					if (isset($existingList[$assetKey][$globalKey][$assetHandle]['output'], $existingList[$assetKey][$globalKey][$assetHandle]['output_min'])) {
						// Save resources: do not update the same values and skip the minification (good to avoid large inline content)
						continue;
					}
					if ( ! isset( $assetArray['output_min'] ) ) {
						$assetArray['output_min'] = '';
						// Reference: $wpacuHardcodedInfoToStoreAfterSubmit from _assets-hardcoded-list.php
						if ( strpos( $assetHandle, 'wpacu_hardcoded_script_' ) === 0 ) {
							$outputMin = \WpAssetCleanUp\OptimiseAssets\MinifyJs::applyMinification( $assetArray['output'] );
							if ( $assetArray['output'] !== $outputMin ) {
								$assetArray['output_min'] = $outputMin;
							}
						} elseif ( ( strpos( $assetHandle, 'wpacu_hardcoded_link_' ) === 0 )
                                   || ( strpos( $assetHandle, 'wpacu_hardcoded_style_' ) === 0 ) ) {
							$outputMin = \WpAssetCleanUp\OptimiseAssets\MinifyCss::applyMinification( $assetArray['output'] );
							if ( $assetArray['output'] !== $outputMin ) {
								$assetArray['output_min'] = $outputMin;
							}
						}
					}
				}
				// [/wpacu_pro]
				$existingList[$assetKey][$globalKey][$assetHandle] = $assetArray;
			}
		}
		update_option($optionToUpdate, wp_json_encode(Misc::filterList($existingList)));
	}
	/**
	 *
	 */
	public static function clearTransients()
	{
		delete_transient(WPACU_PLUGIN_ID. '_total_unloaded_assets_all');
		delete_transient(WPACU_PLUGIN_ID. '_total_unloaded_assets_per_page');
	}
	/**
	 * This is triggered when /admin/admin-ajax.php is called (default WordPress AJAX handler)
	 */
	public function ajaxClearCache()
	{
		if ( ! isset($_REQUEST['wpacu_nonce']) ) {
			echo 'Error: The security nonce was not sent for verification. Location: '.__METHOD__;
			return;
		}
		if ( ! wp_verify_nonce($_REQUEST['wpacu_nonce'], 'wpacu_ajax_clear_cache_nonce') ) {
			echo 'Error: The security check has failed. Location: '.__METHOD__;
			exit();
		}
	    if (! Menu::userCanManageAssets()) {
	        echo 'Error: Not enough privileges to clear the cache.';
	        exit();
        }
		OptimizeCommon::clearCache();
	    exit();
	}
	/**
	 * @return void
	 */
	public function ajaxCacheEnablerClearCache()
    {
	    if ( ! isset($_REQUEST['wpacu_nonce']) ) {
		    echo 'Error: The security nonce was not sent for verification. Location: '.__METHOD__;
		    return;
	    }
	    if ( ! wp_verify_nonce($_REQUEST['wpacu_nonce'], 'wpacu_ajax_clear_cache_enabler_cache_nonce') ) {
		    echo 'Error: The security check has failed. Location: '.__METHOD__;
		    exit();
	    }
	    if (! Menu::userCanManageAssets()) {
		    echo 'Error: Not enough privileges to clear the cache.';
		    exit();
	    }
        OptimizeCommon::clearCacheEnablerCache('ajax_call');
    }
	/**
	 * This is triggered when /admin/admin-ajax.php is called (default WordPress AJAX handler)
	 */
	public function ajaxPreloadGuest()
    {
        // Check nonce
	    if ( ! isset( $_POST['wpacu_nonce'] ) || ! wp_verify_nonce( $_POST['wpacu_nonce'], 'wpacu_ajax_preload_url_nonce' ) ) {
		    echo 'Error: The security nonce is not valid.';
		    exit();
	    }
        $pageUrl = isset($_POST['page_url']) ? $_POST['page_url'] : false;
	    $pageUrlDomain = parse_url($pageUrl, PHP_URL_HOST);
	    $pageUrlPreload = add_query_arg( array( 'wpacu_preload' => 1 ), $pageUrl );
	    // Check if the URL is valid
	    if (! filter_var($pageUrlPreload, FILTER_VALIDATE_URL)) {
		    echo 'The URL `'.$pageUrlPreload.'` is not valid.';
		    exit();
	    }
	    // Check the domain from "page_url" parameter
	    if (strpos(site_url(), $pageUrlDomain) === false) {
	        echo 'Error: Possible hacking attempt! The host name of the requested URL is not the same as the one of "Site Address (URL)" from "Settings" - "General".';
	        exit();
	    }
	    // Check privileges
	    if (! Menu::userCanManageAssets()) {
		    echo 'Error: Not enough privileges to perform this action.';
		    exit();
	    }
	    $response = wp_remote_get($pageUrlPreload);
	    if (is_wp_error($response)) {
	        // Any error generated during the fetch? Print it
	        echo 'Error: '.$response->get_error_code();
	    } else {
	        // No errors
		    echo 'Status Code: '.wp_remote_retrieve_response_code($response).' /  Page URL (preload): ' . $pageUrlPreload . "\n\n";
		    echo isset($response['body']) ? $response['body'] : 'No "body" key found from wp_remote_get(), the preload might not have triggered';
	    }
	    exit();
    }
	/**
	 *
	 */
	public function ajaxUpdateAssetRowState()
    {
	    // Option: "On Assets List Layout Load, keep the groups:"
	    if (isset($_POST['wpacu_update_asset_row_state'])) {
		    if ( ! isset( $_POST['action'], $_POST['wpacu_asset_row_state'], $_POST['wpacu_handle'], $_POST['wpacu_handle_for'] )
                 || ! Menu::userCanManageAssets() ) {
			    return;
		    }
		    if ( $_POST['wpacu_update_asset_row_state'] !== 'yes' ) {
			    return;
		    }
		    if ( ! isset($_POST['wpacu_nonce']) ) {
			    echo 'Error: The security nonce was not sent for verification. Location: '.__METHOD__;
			    return;
		    }
		    if ( ! wp_verify_nonce($_POST['wpacu_nonce'], 'wpacu_update_asset_row_state_nonce') ) {
			    echo 'Error: The security check has failed. Location: '.__METHOD__;
			    return;
		    }
		    $assetRowState = $_POST['wpacu_asset_row_state'];
            $newContractedList = self::updateHandleRowStatus($assetRowState, $_POST['wpacu_handle'], $_POST['wpacu_handle_for']);
		    echo "" . print_r($newContractedList, true);
	    }
	    exit();
    }
	/**
     * Update state for all assets within a plugin
     *
	 * @return void
	 */
	public function ajaxAreaUpdateAssetsRowState()
    {
        if (isset($_POST['wpacu_area_update_assets_row_state'])) {
	        if ( ! isset( $_POST['action'], $_POST['wpacu_area_assets_row_state'], $_POST['wpacu_area_handles'], $_POST['wpacu_nonce'] )
	             || ! Menu::userCanManageAssets() ) {
		        return;
	        }
	        if ( $_POST['wpacu_area_update_assets_row_state'] !== 'yes' ) {
		        return;
	        }
	        if ( ! isset($_POST['wpacu_nonce']) ) {
		        echo 'Error: The security nonce was not sent for verification. Location: '.__METHOD__;
		        return;
	        }
	        if ( ! wp_verify_nonce($_POST['wpacu_nonce'], 'wpacu_area_update_assets_row_state_nonce') ) {
		        echo 'Error: The security check has failed. Location: '.__METHOD__;
		        return;
	        }
	        $areaAllAssetsRowState = $_POST['wpacu_area_assets_row_state'];
            if ( ! empty($_POST['wpacu_area_handles']) && is_array($_POST['wpacu_area_handles']) ) {
                foreach ($_POST['wpacu_area_handles'] as $areaAssetHandleFormat) {
	                $areaAssetHandleFor = substr(strrchr($areaAssetHandleFormat, '_'), 1);
                    $areaAssetHandle    = substr($areaAssetHandleFormat, 0, -(strlen($areaAssetHandleFor) + 1));
	                echo 'New State: '.$areaAllAssetsRowState.' / Handle: '.$areaAssetHandle . ' / For: '.$areaAssetHandleFor."\n";
	                $newContractedList = self::updateHandleRowStatus( $areaAllAssetsRowState, $areaAssetHandle, $areaAssetHandleFor );
	                echo "" . print_r( $newContractedList, true );
                }
            }
	        exit();
        }
    }
}