'WPCode', 'elementor_snippet' => 'Elementor Pro', 'custom-css-js' => 'Simple Custom CSS and JS', 'wbcr-snippets' => 'Woody Code Snippets', ); /** * Post types of theme layouts that can run PHP, with the plugin that * runs them: a GeneratePress Hook element executes PHP when its box is * ticked, and an Astra Custom Layout can hold PHP in its code editor. */ public const LAYOUT_TYPES = array( 'gp_elements' => 'GeneratePress Premium', 'astra-advanced-hook' => 'Astra Pro', ); /** * Plugins whose abilities run only when they are known to be read-only * (READ_ONLY_ABILITIES), by ability namespace. Any other ability in the * namespace, now or in a later version of the plugin, is not run. */ public const ABILITY_NAMESPACES = array( 'wpcode' => 'WPCode', ); /** * The abilities of those plugins that only read. WPCode 2.4.1 marks * exactly these read-only. */ public const READ_ONLY_ABILITIES = array( 'wpcode/list-snippets', 'wpcode/get-snippet', 'wpcode/detect-snippet-errors', 'wpcode/get-error-logs', 'wpcode/search-library', 'wpcode/get-settings', 'wpcode/get-headers-footers', ); /** * WPCode's abilities known to add, change or switch on code. */ public const ABILITIES = array( 'wpcode/create-snippet', 'wpcode/update-snippet', 'wpcode/set-snippet-status', 'wpcode/update-headers-footers', 'wpcode/install-library-snippet', ); /** * Whether this site's plan lets the tools change code snippets. Only the * paid version can say yes; the plugin from WordPress.org never does. */ public static function writable(): bool { return class_exists( \GripMCP\Premium\Paid_Writes::class ) && \GripMCP\Premium\Paid_Writes::snippets(); } /** * Every post type kept whole: the lists above, and any a site adds * through the gripmcp/code_post_types filter. The filter only adds: a * type listed here stays listed whatever it returns. * * @return array Post type => plugin that runs its code. */ public static function types(): array { $types = self::TYPES + self::LAYOUT_TYPES; /** * Filter: more post types holding code that another plugin runs on * the site. GripMCP then reads their posts but does not create, * change, restore or delete them, unless the site's plan changes code. * * @param array $extra Post type => plugin name, or a plain list of post types. */ $extra = apply_filters( 'gripmcp/code_post_types', array() ); foreach ( is_array( $extra ) ? $extra : array() as $key => $value ) { $type = is_int( $key ) ? $value : $key; $plugin = is_int( $key ) ? '' : $value; if ( ! is_string( $type ) ) { continue; } $type = sanitize_key( $type ); if ( '' !== $type && ! isset( $types[ $type ] ) ) { $types[ $type ] = is_string( $plugin ) && '' !== trim( $plugin ) ? trim( $plugin ) : $type; } } return $types; } /** * Whether a post type holds another plugin's code. * * @param string $type Post type. */ public static function is_type( string $type ): bool { return isset( self::types()[ $type ] ); } /** * Whether an ability may add, change or switch on another plugin's code: * any ability in a namespace listed in ABILITY_NAMESPACES that is not * one of its known read-only abilities. Compared in lower case, as the * Abilities API stores names. * * @param string $name Ability name. */ public static function is_ability( string $name ): bool { $name = strtolower( trim( $name ) ); $slash = strpos( $name, '/' ); return false !== $slash && isset( self::ABILITY_NAMESPACES[ substr( $name, 0, $slash ) ] ) && ! in_array( $name, self::READ_ONLY_ABILITIES, true ); } /** * Why a code snippet post was not created or changed. * * @param string $type Post type. */ public static function post_error( string $type ): string { if ( isset( self::LAYOUT_TYPES[ $type ] ) ) { return sprintf( /* translators: 1: post type, e.g. "gp_elements", 2: plugin, e.g. "GeneratePress Premium". */ __( '"%1$s" is a %2$s layout, which can run PHP on the site. GripMCP can read it but does not create, change, restore or delete it; that is done on %2$s\'s own screen in wp-admin. Nothing was changed.', 'gripmcp' ), $type, self::LAYOUT_TYPES[ $type ] ); } return sprintf( /* translators: 1: post type, e.g. "wpcode", 2: plugin, e.g. "WPCode". */ __( '"%1$s" is a %2$s code snippet: code that runs on the site. GripMCP can read it but does not create, change, restore or delete it; that is done on %2$s\'s own screen in wp-admin. Nothing was changed.', 'gripmcp' ), $type, self::types()[ $type ] ?? $type ); } /** * Why a code-writing ability was not run. * * @param string $name Ability name. */ public static function ability_error( string $name ): string { $key = strtolower( trim( $name ) ); $slash = strpos( $key, '/' ); $plugin = false === $slash ? 'WPCode' : ( self::ABILITY_NAMESPACES[ substr( $key, 0, $slash ) ] ?? 'WPCode' ); if ( in_array( $key, self::ABILITIES, true ) ) { return sprintf( /* translators: 1: ability name, e.g. "wpcode/create-snippet", 2: plugin, e.g. "WPCode". */ __( 'The ability "%1$s" adds or changes code that runs on the site, so GripMCP does not run it. That is done on %2$s\'s own screen in wp-admin; %2$s\'s read-only abilities still work. Nothing was changed.', 'gripmcp' ), $name, $plugin ); } return sprintf( /* translators: 1: ability name, 2: plugin, e.g. "WPCode". */ __( 'The ability "%1$s" is not one of %2$s\'s read-only abilities, so GripMCP does not run it: %2$s\'s other abilities add or change code that runs on the site. The person can use it on %2$s\'s own screen in wp-admin; %2$s\'s read-only abilities still work. Nothing was changed.', 'gripmcp' ), $name, $plugin ); } }