{$class}; $propsKeys = array_keys($props); $styleObject = '{'; foreach ($propsKeys as $property) { $value = $props[$property]; if (empty($value)) { continue; } if (is_object($value)) { continue; } $styleObject .= "{$property}:{$value}{$important};"; } $styleObject = rtrim($styleObject, ';'); $styleObject .= '}'; $css .= $styleObject; } return $css; } public static function convertToCSS(array $styles): string { $css = ''; foreach ($styles as $selector => $properties) { $css .= "$selector{"; // Check if the properties are an array, meaning it's a nested rule (e.g., media queries, keyframes) if (is_array($properties)) { // If it's a nested array (media query or keyframe), recursively handle it foreach ($properties as $property => $value) { if (is_array($value)) { // Recursively process nested arrays (media queries, keyframes, etc.) $css .= self::convertToCSS([$property => $value]); } else { // Regular CSS property $css .= "$property:$value;"; } } } $css .= '}'; } return $css; } public static function appendCSS($formId, $css, $mode = 'a') { $fileName = ''; $path = ''; $path = 'form-styles'; $fileName = "bitform-{$formId}.css"; Helpers::saveFile($path, $fileName, $css, $mode); $fileName = "bitform-{$formId}-formid.css"; Helpers::saveFile($path, $fileName, $css, $mode); } /** * First row of a Model/get() style result, or null when the lookup failed * (WP_Error), returned an empty set, or has no index 0. Prevents * "Attempt to read property on null" when dereferencing $result[0]->col. * * @param mixed $result * @return object|null */ public static function firstRow($result) { if (is_wp_error($result) || empty($result) || !isset($result[0])) { return null; } return $result[0]; } /** * Decode a JSON string to an object, guaranteed to return object|null so * downstream `$obj->prop ?? default` reads never emit an undefined-property * warning. Returns null for non-strings, empty strings and malformed JSON. * * @param mixed $json * @return object|null */ public static function jsonObj($json) { if (!is_string($json) || '' === $json) { return null; } $decoded = json_decode($json); return is_object($decoded) ? $decoded : null; } /** * Hardened hosts disable ignore_user_abort in php.ini; PHP 8 fatals on the call instead of warning. * * @param bool $ignore * @return void */ public static function ignoreUserAbort($ignore = true) { if (\function_exists('ignore_user_abort')) { \ignore_user_abort($ignore); } } public static function duplicateDbTable($oldTableName, $newTableName) { global $wpdb; $oldTable = "{$wpdb->prefix}bitforms_{$oldTableName}"; $newTable = "{$wpdb->prefix}bitforms_{$newTableName}"; // Schema operation: table name interpolation only (no user input). $wpdb->prepare() cannot parameterize DDL statements. $wpdb->query("CREATE TABLE IF NOT EXISTS `{$newTable}` LIKE `{$oldTable}`"); $wpdb->query("INSERT INTO `{$newTable}` SELECT * FROM `{$oldTable}`"); } }