tegory Name", taxonomy => "categoryTaxonomy" ], * [id => "categoryId2", name => "Category Name2", taxonomy => "categoryTaxonomy" ], * ... * ] * * @return array Modified categories. * @since 1.6.3 * @since 1.8.0 Updates the structure of the categories array. */ $categories = apply_filters('wpcc/categories', $categories); return $categories; } /** * Get custom post category taxonomies defined in the general settings * * @return array A key-value pair where keys are the taxonomies and the values are their descriptions. * @since 1.8.0 */ private static function getCustomPostCategoryTaxonomies() { // Get custom post category taxonomies defined in the general settings $customPostTaxonomiesInSettings = get_option('_wpcc_post_category_taxonomies'); if (!$customPostTaxonomiesInSettings) return []; $customTaxonomies = []; foreach($customPostTaxonomiesInSettings as $data) { $taxonomyName = Utils::array_get($data, 'taxonomy'); $description = Utils::array_get($data, 'description', ''); // If there is no taxonomy name, continue with the next one. if (!$taxonomyName) continue; $customTaxonomies[$taxonomyName] = $description; } return $customTaxonomies; } /** * Get a value from an array * * @param array $array The array * @param string $key The key whose value is wanted * @param mixed $default Default value if the value of the key is not valid * @return mixed Value of the key or the default value */ public static function getValueFromArray($array, $key, $default = false) { return isset($array[$key]) && $array[$key] ? $array[$key] : $default; } /** * Check if the user wants to change the password for the posts. If not, remove the password field. * * @param array $data Input data from user, such as $_POST * @param array $keys Available setting (post meta) keys * @param null|string $oldPassword Old password to check against. If null, general option will be used to get an * old password. * @return array An array having 'success' and 'message' keys, with data types boolean and string, respectively. */ public static function validatePasswordInput(&$data, &$keys, $oldPassword = null) { $success = true; $message = ''; if(!isset($data['_wpcc_change_password'])) { unset($data['_wpcc_post_password']); unset($keys[array_search('_wpcc_post_password', $keys)]); } else { // Check if the old pw is correct $oldPassword = $oldPassword === null ? get_option('_wpcc_post_password') : $oldPassword; if($oldPassword !== $data["_wpcc_post_password_old"]) { // Old password is not correct. Remove the password from data and keys, and set success as false. unset($data['_wpcc_post_password']); unset($keys[array_search('_wpcc_post_password', $keys)]); $success = false; $message = 'Old password is not correct.'; } else { // Check if passwords match if($data["_wpcc_post_password"] !== $data["_wpcc_post_password_validation"]) { $success = false; $message = _wpcc('Passwords do not match.'); } } } return [ 'success' => $success, 'message' => $message ]; } /** * Delete a file * * @param string $filePath */ public static function deleteFile($filePath) { if(!$filePath) return; wp_delete_file($filePath); } /** * Delete a post's thumbnail and the attachment. * * @param int $postId ID of the post whose thumbnail should be deleted */ public static function deletePostThumbnail($postId) { // Get the ID of the thumbnail attachment $alreadyExistingThumbId = get_post_thumbnail_id($postId); // Delete the thumbnail from the post delete_post_thumbnail($postId); // Delete the attachment if($alreadyExistingThumbId) wp_delete_attachment($alreadyExistingThumbId); } /** * Convert encoding of a string * * @param string $string The string whose encoding will be converted * @param string $targetEncoding Target encoding * @return mixed|string Resultant string */ public static function convertEncoding($string, $targetEncoding = 'UTF-8') { return mb_convert_encoding($string, $targetEncoding, mb_detect_encoding($string, 'UTF-8, ISO-8859-1', true)); } /** * Chunks the given flat array such that total length of texts in a chunk does not exceed the given total length. * The given array should not have keys. The array must contain only strings as values. The array must not contain * inner arrays. * * Note: This method does not change the indices of the given array. It chunks the array by checking every next item. * So, this does not chunk the array in an optimal way. * * Note: If there is an item whose length exceeds the defined max length per chunk, a chunk will be created for that * item itself. This method does not cut the texts. * * @param array $arr A flat array (i.e. no inner arrays) containing text as values. * @param int $maxLengthPerChunk Maximum text length per chunk. * * @return array An array of chunks. */ public static function chunkArrayByTotalTextLength($arr, $maxLengthPerChunk) { // Stores the final chunks $chunks = []; // Stores current total character count for the next chunk. $currentTotal = 0; // Stores the index of the item that was last included into a chunk. $lastUsedIndex = -1; $arrLength = sizeof($arr); $lastItemIndex = $arrLength - 1; for($i = 0; $i < $arrLength; $i++) { $currentTotal += mb_strlen($arr[$i]); // If the current total is greater than or equal to max length per chunk if($currentTotal >= $maxLengthPerChunk) { // If the total length equals the max length if($currentTotal == $maxLengthPerChunk) { // Create a chunk from last used index to the current index, including the current index. $chunks[] = array_slice($arr, $lastUsedIndex + 1, $i - $lastUsedIndex); // If current total is greater than the limit } else { // If there is only one item that exceeds the total chunk length, create a chunk for that item. if($i - $lastUsedIndex == 1) { $chunks[] = array_slice($arr, $lastUsedIndex + 1, 1); // Otherwise } else { // Create chunk from last used index to the current index, excluding the current index. $chunks[] = array_slice($arr, $lastUsedIndex + 1, $i - $lastUsedIndex - 1); // Decrease the index by 1, since we did not include the current index into a chunk. So, // start counting the total from the current index. $i--; } } // Assign the current index as the last used index. $lastUsedIndex = $i; // Reset the current total, since we already created a chunk and are starting over. $currentTotal = 0; // If the current total is not greater than or equal to max text length per chunk and this is the last item // in the given array, create a chunk including all left-out items. } else if ($i == $lastItemIndex) { $chunks[] = array_slice($arr, $lastUsedIndex + 1, $i - $lastUsedIndex); } } return $chunks; } /** * @param string $name Name of the term * @param string $taxonomy Taxonomy of the term * @param array|string $args Other arguments. See {@link wp_insert_term()}. * @return int|null If the term is inserted or it exists, its ID. Otherwise, null. */ public static function insertTerm($name, $taxonomy, $args = []) { $result = wp_insert_term($name, $taxonomy, $args); $termId = null; $errorMessage = null; if (!is_wp_error($result) && !empty($result['term_taxonomy_id'])) { $termId = absint($result['term_taxonomy_id']); } else if(is_wp_error($result)) { $termId = $result->get_error_data( 'term_exists' ); // The term could not be inserted. Try to get the error message. if (!$termId) { $errorMessage = $result->get_error_message(); } } // If the term could not be inserted or retrieved, inform the user. if ($termId === null) { $argsInfo = json_encode($args); if ($argsInfo === false) $argsInfo = ''; Informer::addError(sprintf( _wpcc('Term "%1$s" could not be added to taxonomy "%2$s" (Args: %3$s). Message: %4$s'), $name, $taxonomy, $argsInfo, isset($errorMessage) && $errorMessage ? $errorMessage : '-') )->addAsLog(); } return $termId; } /** * Separates the strings with the given separators and returns a flat array. E.g. if the given array is * ["val1, val2", "val3, val4 | val5"] with separators given as [",", "|"], the result will be * ["val1, "val2", "val3", "val4", "val5"] * * @param array|string $values An array of strings or a string. * @param array $separators An array of separators. E.g. [",", "|"] * @param bool $trim True if the values should be trimmed. * @return array A flat array that contains separated values. * @since 1.8.0 */ public static function getSeparated($values, $separators, $trim = true) { // If there is no value, stop. if (!$values) return []; // If the value is not an array, make it an array. if (!is_array($values)) $values = [$values]; // Create splitter regex // This will turn [',', '-', '/'] into ',|-|\/' $splitPart = implode('|', array_map(function($separator) { return preg_quote($separator, '/'); }, $separators)); // If there is no split part, stop. if (!$splitPart) return $values; // Create the final splitter regex $splitRegex = $splitPart ? "/($splitPart)/" : null; $preparedValues = []; $separatorListStrForNotification = null; $valueListStrForNotification = null; foreach($values as $valStr) { $res = preg_split($splitRegex, $valStr); // If there is an error, notify the user and continue with the next string. if ($res === false) { if ($separatorListStrForNotification === null) $separatorListStrForNotification = implode(' ', $separators); if ($valueListStrForNotification === null) $valueListStrForNotification = implode(' ', $values); Informer::addError(sprintf( _wpcc('%1$s could not be separated using these separators: %2$s'), $valueListStrForNotification, $separatorListStrForNotification) )->addAsLog(); continue; } $preparedValues[] = $res; } // Make sure we have a flat array. $preparedValues = array_flatten($preparedValues); // Prepare the items $preparedValues = array_values(array_filter(array_map(function($v) use (&$trim) { // Remove the item if it is not valid. if (!$v) return null; // Trim it if it is required. $result = $trim ? trim($v) : $v; // If the item is still valid, return it. Otherwise, remove it. return $result ? $result : null; }, $preparedValues))); return array_values($preparedValues); } /** * Converts encoding of the given items from UTF8 to UTF8 to fix mixed UTF8 char problems caused when parsing * to JSON. The specific error is "Malformed UTF-8 characters, possibly incorrectly encoded" ({@link JSON_ERROR_UTF8}) * retrieved from {@link json_last_error()}. * * @param mixed $data The data whose mixed encoding should be fixed * @return mixed * @since 1.8.0 * @see https://stackoverflow.com/a/52641198/2883487 */ public static function deepFixMixedUTF8Encoding($data) { if (is_array($data)) { foreach ($data as $key => $value) { $data[$key] = static::deepFixMixedUTF8Encoding($value); } } else if (is_string($data)) { return mb_convert_encoding($data, "UTF-8", "UTF-8"); } return $data; } /** * Get current locale's code. The language code's part that comes before underscore '_' char is returned. * * @return string Language code of the current locale of WP * @since 1.8.0 */ public static function getLocaleCode() { // Get the locale from WP $locale = get_locale(); // If there exists a locale and it contains an underscore if ($locale && str_contains($locale, '_')) { // Get the part coming before the underscore $exploded = explode('_', $locale); $locale = $exploded[0]; // Otherwise, if there is no locale, set a default code. } else if (!$locale) { $locale = 'en'; } return $locale; } }