* A user must have at least one out of the 'update_core', 'install_plugins', and * 'install_themes' capabilities to qualify for 'install_languages'. * * @since 4.9.0 * * @param bool[] $allcaps An array of all the user's capabilities. * @return bool[] Filtered array of the user's capabilities. */ function wp_maybe_grant_install_languages_cap( $allcaps ) { if ( ! empty( $allcaps['update_core'] ) || ! empty( $allcaps['install_plugins'] ) || ! empty( $allcaps['install_themes'] ) ) { $allcaps['install_languages'] = true; } return $allcaps; } /** * Filters the user capabilities to grant the 'resume_plugins' and 'resume_themes' capabilities as necessary. * * @since 5.2.0 * * @param bool[] $allcaps An array of all the user's capabilities. * @return bool[] Filtered array of the user's capabilities. */ function wp_maybe_grant_resume_extensions_caps( $allcaps ) { // Even in a multisite, regular administrators should be able to resume plugins. if ( ! empty( $allcaps['activate_plugins'] ) ) { $allcaps['resume_plugins'] = true; } // Even in a multisite, regular administrators should be able to resume themes. if ( ! empty( $allcaps['switch_themes'] ) ) { $allcaps['resume_themes'] = true; } return $allcaps; } /** * Filters the user capabilities to grant the 'view_site_health_checks' capabilities as necessary. * * @since 5.2.2 * * @param bool[] $allcaps An array of all the user's capabilities. * @param string[] $caps Required primitive capabilities for the requested capability. * @param array $args { * Arguments that accompany the requested capability check. * * @type string $0 Requested capability. * @type int $1 Concerned user ID. * @type mixed ...$2 Optional second and further parameters, typically object ID. * } * @param WP_User $user The user object. * @return bool[] Filtered array of the user's capabilities. */ function wp_maybe_grant_site_health_caps( $allcaps, $caps, $args, $user ) { if ( ! empty( $allcaps['install_plugins'] ) && ( ! is_multisite() || is_super_admin( $user->ID ) ) ) { $allcaps['view_site_health_checks'] = true; } return $allcaps; } return; // Dummy gettext calls to get strings in the catalog. /* translators: User role for administrators. */ _x( 'Administrator', 'User role' ); /* translators: User role for editors. */ _x( 'Editor', 'User role' ); /* translators: User role for authors. */ _x( 'Author', 'User role' ); /* translators: User role for contributors. */ _x( 'Contributor', 'User role' ); /* translators: User role for subscribers. */ _x( 'Subscriber', 'User role' ); array(); if ( preg_match( '/(.*)-(\d+x\d+|scaled)-' . $number . '$/', $name, $matches ) ) { $filename_without_suffix = $matches[1] . '-' . $matches[2] . ".$ext"; if ( $matches[1] === $orig_name && ! file_exists( "$dir/$filename_without_suffix" ) ) { return $filename_without_suffix; } } return $filename; } /** * Validates the `sub_sizes` file names against what this attachment produced. * * The {@see self::finalize_item()} method stores the client-supplied `file` * and `original_image` values in the attachment metadata, where they are * later resolved within the attachment's upload directory and read or deleted * (for example by {@see wp_get_original_image_path()}, {@see wp_getimagesize()}, * and {@see wp_delete_attachment_files()}). * * Every file the sideload endpoint creates is recorded under * {@see self::META_KEY_SIDELOAD_FILE_NAME} as it is produced, using * server-generated names. finalize accepts a `file` or `original_image` * value only when it matches one of those recorded names (or the * attachment's own attached file, which it definitionally owns). * * @since 7.1.0 * * @param int $attachment_id The attachment being finalized. * @param array $sub_sizes Sub-size metadata collected from sideloads. * @return true|WP_Error True if every file name was produced here, WP_Error otherwise. * * @phpstan-param list $sub_sizes */ protected function validate_sub_size_provenance( int $attachment_id, array $sub_sizes ) { $allowed = $this->get_sideloaded_file_names( $attachment_id ); foreach ( $sub_sizes as $sub_size ) { foreach ( array( 'file', 'original_image' ) as $key ) { /* * Every value that was sent is checked, no matter how unlikely * a name it looks. A loose emptiness test would wave through * '0', which is a valid one-character name as far as the schema * is concerned and is stored like any other. A value the schema * types as a string but which arrives as something else is * rejected rather than skipped, so a subclass which widens the * schema cannot pass an unchecked value on to the metadata. */ if ( ! isset( $sub_size[ $key ] ) ) { continue; } if ( ! is_string( $sub_size[ $key ] ) || ! in_array( $sub_size[ $key ], $allowed, true ) ) { return new WP_Error( 'rest_invalid_sub_size_file', __( 'Invalid sub-size file name. File names must have been produced by a prior sideload for this attachment.' ), array( 'status' => 400 ) ); } } } return true; } /** * Returns the file names which a finalize request may store for an attachment. * * The set is the file names the sideload endpoint recorded as it produced * them (ref. {@see self::META_KEY_SIDELOAD_FILE_NAME}), plus the attachment's own * attached file - accepted in both its uploads-relative and basename form so * a scaled main-file pointer validates regardless of which the client * echoes - plus the names already stored in the attachment's own metadata. * * @since 7.1.0 * * @param int $attachment_id The attachment being finalized. * @param bool $include_provenance Whether to include the sideload provenance rows. * Pass false to get only the names recoverable from * the attached file and stored metadata, e.g. to decide * whether a provenance row is still needed. Default true. * @return string[] File names that may appear in the finalize submission. * * @phpstan-return list */ protected function get_sideloaded_file_names( int $attachment_id, bool $include_provenance = true ): array { $allowed = array(); if ( $include_provenance ) { foreach ( (array) get_post_meta( $attachment_id, self::META_KEY_SIDELOAD_FILE_NAME ) as $name ) { if ( is_string( $name ) && '' !== $name ) { $allowed[] = $name; } } } $attached_file = get_post_meta( $attachment_id, '_wp_attached_file', true ); if ( is_string( $attached_file ) && strlen( $attached_file ) > 0 ) { $allowed[] = $attached_file; $allowed[] = wp_basename( $attached_file ); } /* * Names already stored in this attachment's metadata passed this same * check when they were written, so accepting them again introduces * nothing new. */ $metadata = wp_get_attachment_metadata( $attachment_id, true ); if ( is_array( $metadata ) ) { $stored = array( $metadata['file'] ?? null, $metadata['original_image'] ?? null, $metadata[ self::META_KEY_SOURCE_IMAGE ] ?? null, $metadata['animated_video'] ?? null, $metadata['animated_video_poster'] ?? null, ); if ( ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ) { foreach ( $metadata['sizes'] as $size ) { $stored[] = is_array( $size ) ? ( $size['file'] ?? null ) : null; } } foreach ( $stored as $name ) { if ( is_string( $name ) && '' !== $name ) { $allowed[] = $name; $allowed[] = wp_basename( $name ); } } } return array_values( array_unique( $allowed ) ); } /** * Returns the uploads subdirectory an attachment is stored in. * * Used to place a sideloaded file alongside the attachment it extends. The * result is concatenated into a filesystem path by the caller, so it is * returned only when the attachment resolves inside the uploads directory * and the stored path is well formed. * * @since 7.1.0 * * @param string $attached_file Absolute path to the attached file. * @return string|null Subdirectory beginning with a slash, an empty string when the * attachment sits in the base directory, or null when the * attachment is not inside the uploads directory. * * @phpstan-param non-empty-string $attached_file */ protected function get_attachment_upload_subdir( string $attached_file ): ?string { $uploads = wp_get_upload_dir(); if ( empty( $uploads['basedir'] ) ) { return null; } $basedir = untrailingslashit( wp_normalize_path( $uploads['basedir'] ) ); $file_dir = wp_normalize_path( dirname( $attached_file ) ); /* * The attachment's directory must be the uploads base directory itself * or a directory inside it. The trailing slash in the prefix comparison * keeps a sibling directory that merely shares the prefix (for example * 'uploads-elsewhere' next to 'uploads') from matching. */ if ( $file_dir !== $basedir && ! str_starts_with( $file_dir, trailingslashit( $basedir ) ) ) { return null; } $subdir = (string) substr( $file_dir, strlen( $basedir ) ); // A prefix match alone does not rule out a path that climbs back out. if ( in_array( '..', explode( '/', $subdir ), true ) ) { return null; } return $subdir; } /** * Finalizes an attachment after client-side media processing. * * Applies the sub-size metadata collected from sideload responses in a * single metadata update, then triggers the 'wp_generate_attachment_metadata' * filter so that server-side plugins can process the attachment after all * client-side operations (upload, thumbnail generation, sideloads) are * complete. * * @since 7.1.0 * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. */ public function finalize_item( WP_REST_Request $request ) { $attachment_id = (int) $request['id']; $post = $this->get_post( $attachment_id ); if ( is_wp_error( $post ) ) { return $post; } /** * Sub-size metadata collected from sideload responses. Confirm every * file name was produced by a prior sideload for this attachment before * storing it, so a client cannot make finalize record (and later read or * delete) another attachment's files. * * @var list $sub_sizes */ $sub_sizes = $request['sub_sizes'] ?? array(); $provenance = $this->validate_sub_size_provenance( $attachment_id, $sub_sizes ); if ( is_wp_error( $provenance ) ) { return $provenance; } $metadata = wp_get_attachment_metadata( $attachment_id ); if ( ! is_array( $metadata ) ) { $metadata = array(); } // Apply all sub-size metadata collected from sideload responses. foreach ( $sub_sizes as $sub_size ) { $image_size = $sub_size['image_size']; // When multiple size names share identical dimensions the client // sends a single sub-size entry with an array of names. Register the // same file under each name. if ( is_array( $image_size ) ) { /* * Arrays carry regular sizes only, as the sideload endpoint * enforces. Each special size names a single file handled by one * of the branches below, so grouping one under a shared file * would write it to the wrong place; reject rather than guess. */ if ( array_intersect( $image_size, self::get_special_image_sizes() ) ) { return new WP_Error( 'rest_invalid_sub_size_name', __( 'A grouped sub-size entry may only name regular image sizes.' ), array( 'status' => 400 ) ); } // As below: `file` is not required by the schema, and a size // entry that names no file is not worth recording. if ( empty( $sub_size['file'] ) ) { continue; } $metadata['sizes'] = $metadata['sizes'] ?? array(); foreach ( $image_size as $name ) { $metadata['sizes'][ $name ] = array( 'width' => $sub_size['width'] ?? 0, 'height' => $sub_size['height'] ?? 0, 'file' => $sub_size['file'], 'mime-type' => $sub_size['mime_type'] ?? '', 'filesize' => $sub_size['filesize'] ?? 0, ); } continue; } if ( 'original' === $image_size || 'scaled' === $image_size ) { // Skip malformed entries so a bad payload cannot blank out the // main file metadata. if ( empty( $sub_size['file'] ) ) { continue; } /* * Record the supplied full-size image (from sideload_item()) as * the main file, keeping the current attached file as * `original_image`. A 'scaled' image is downsized and an * 'original' image is rotated; both have any EXIF orientation * already applied by the client. */ if ( ! empty( $sub_size['original_image'] ) ) { $metadata['original_image'] = $sub_size['original_image']; } $metadata['width'] = $sub_size['width'] ?? 0; $metadata['height'] = $sub_size['height'] ?? 0; $metadata['filesize'] = $sub_size['filesize'] ?? 0; $metadata['file'] = $sub_size['file']; /* * The supplied image has its orientation applied already, so * reset the stored value (from the upload) to 1, as * wp_create_image_subsizes() does for both its scale and rotate * paths. Otherwise exif_orientation would still report the * pre-rotation value and the client would rotate the image * again on a re-fetch. */ if ( ! empty( $metadata['image_meta']['orientation'] ) ) { $metadata['image_meta']['orientation'] = 1; } } elseif ( self::IMAGE_SIZE_SOURCE_ORIGINAL === $image_size ) { // As above: `file` is not required by the schema, and each of // these sizes is nothing but the file it names. if ( empty( $sub_size['file'] ) ) { continue; } /* * Source-format original: stored under its own meta key so the * scaled-sideload flow (which writes 'original_image') cannot * clobber it. 'original_image' keeps pointing at the * web-viewable JPEG derivative. Cleanup on attachment delete * is handled by wp_delete_attachment_files(). */ $metadata[ self::META_KEY_SOURCE_IMAGE ] = $sub_size['file']; } elseif ( 'animated_video' === $image_size ) { if ( empty( $sub_size['file'] ) ) { continue; } /* * Converted-video companion of an animated GIF. Stored under its * own meta key; 'original_image' keeps pointing at the GIF. Cleanup * on attachment delete is handled by wp_delete_attachment_files(). */ $metadata['animated_video'] = $sub_size['file']; } elseif ( 'animated_video_poster' === $image_size ) { if ( empty( $sub_size['file'] ) ) { continue; } // Static first-frame poster for the converted video. $metadata['animated_video_poster'] = $sub_size['file']; } else { if ( empty( $sub_size['file'] ) ) { continue; } $metadata['sizes'] = $metadata['sizes'] ?? array(); $metadata['sizes'][ $image_size ] = array( 'width' => $sub_size['width'] ?? 0, 'height' => $sub_size['height'] ?? 0, 'file' => $sub_size['file'], 'mime-type' => $sub_size['mime_type'] ?? '', 'filesize' => $sub_size['filesize'] ?? 0, ); } } /** This filter is documented in wp-admin/includes/image.php */ $metadata = apply_filters( 'wp_generate_attachment_metadata', $metadata, $attachment_id, 'update' ); wp_update_attachment_metadata( $attachment_id, $metadata ); /* * Drop only the provenance rows this request consumed, now that the * names are recorded in the metadata itself. A row is dropped only once * its name is recoverable from the stored metadata, so a name the * 'wp_generate_attachment_metadata' filter removed - or that a failed * update never persisted - keeps its row and the retried request the * endpoint documents as idempotent still validates. Rows for sideloads * that have not been finalized yet survive for a later call, and passing * the value makes the delete a no-op when the row is already gone, so a * retried request cleans up without error. Any rows left behind by an * abandoned upload are removed with the attachment itself. * * Retrying is idempotent for the request as it was sent. A name is only * unavailable to a retry once a later finalize has overwritten the same * size with a newly sideloaded file, which drops the earlier name from * the metadata the retry recovers it from. * * The names are collected before deleting so a request which repeats * the same name across many sub-sizes still issues one query per * distinct name. */ $recoverable = $this->get_sideloaded_file_names( $attachment_id, false ); $consumed = array(); foreach ( $sub_sizes as $sub_size ) { foreach ( array( 'file', 'original_image' ) as $key ) { // Matches the set validate_sub_size_provenance() checked, so // every name a request was allowed to store is also cleaned up. if ( isset( $sub_size[ $key ] ) && is_string( $sub_size[ $key ] ) && in_array( $sub_size[ $key ], $recoverable, true ) ) { $consumed[] = $sub_size[ $key ]; } } } foreach ( array_unique( $consumed ) as $file_name ) { delete_post_meta( $attachment_id, self::META_KEY_SIDELOAD_FILE_NAME, wp_slash( $file_name ) ); } $response_request = new WP_REST_Request( WP_REST_Server::READABLE, rest_get_route_for_post( $attachment_id ) ); $response_request['context'] = 'edit'; if ( isset( $request['_fields'] ) ) { $response_request['_fields'] = $request['_fields']; } /* * Re-read the post. The 'wp_generate_attachment_metadata' filter above * runs long after $post was fetched, and a callback that rewrites the * post row - an optimizer changing post_mime_type once it has * converted the file, say - would otherwise be missing from this * response. The editor stores the response as its copy of the record * rather than reading the attachment again, so a stale row here is * what it keeps. A callback that deleted the attachment instead leaves * nothing to respond with, so that is reported as the error it is. */ $post = $this->get_post( $attachment_id ); if ( is_wp_error( $post ) ) { return $post; } return $this->prepare_item_for_response( $post, $response_request ); } }
Fatal error: require_once(): Failed opening required '/home/he2a35ddd308f/public_html/wp-content/plugins/breeze/inc/breeze-admin.php' (include_path='.:/opt/alt/php74/usr/share/pear') in /home/he2a35ddd308f/public_html/wp-content/plugins/breeze/breeze.php on line 104