WP_REST_Server::READABLE, 'callback' => [ $this, 'get_snippets_info' ], 'permission_callback' => function () { return current_user_can( 'edit_posts' ); }, ) ); } /** * Fetch snippets data in response to a request. * * @return WP_REST_Response */ public function get_snippets_info(): WP_REST_Response { $snippets = get_snippets(); $data = []; foreach ( $snippets as $snippet ) { $data[] = [ 'id' => $snippet->id, 'name' => $snippet->name, 'type' => $snippet->type, 'active' => $snippet->active, ]; } return new WP_REST_Response( $data, 200 ); } /** * Perform the necessary actions to add a button to the TinyMCE editor */ public function setup_mce_plugin() { if ( ! code_snippets()->current_user_can() ) { return; } /* Register the TinyMCE plugin */ add_filter( 'mce_external_plugins', function ( $plugins ) { $plugins['code_snippets'] = plugins_url( 'dist/mce.js', PLUGIN_FILE ); return $plugins; } ); /* Add the button to the editor toolbar */ add_filter( 'mce_buttons', function ( $buttons ) { $buttons[] = 'code_snippets'; return $buttons; } ); /* Add the translation strings to the TinyMCE editor */ add_filter( 'mce_external_languages', function ( $languages ) { $languages['code_snippets'] = __DIR__ . '/mce-strings.php'; return $languages; } ); } /** * Enqueue the syntax highlighting assets if they are required for the current posts * * @param array|null|false $posts List of currently visible posts. * * @return array|null|false Unchanged list of posts. */ public function enqueue_highlighting( $posts ) { // Exit early if there are no posts to check or if the highlighter has been disabled. if ( empty( $posts ) || Settings\get_setting( 'general', 'disable_prism' ) ) { return $posts; } // Loop through the posts, checking for an existing shortcode, short-circuiting if possible. $found_shortcode_content = null; foreach ( $posts as $post ) { if ( false !== stripos( $post->post_content, '[' . self::SOURCE_SHORTCODE ) || false !== strpos( $post->post_content, ''; } $depth++; $atts = shortcode_parse_atts( $matches[1] ); $result = $this->render_content_shortcode( $atts ); $depth--; return $result; }, $content ); // Add this shortcode back to the list. add_shortcode( self::CONTENT_SHORTCODE, [ $this, 'render_content_shortcode' ] ); } return apply_filters( 'code_snippets/content_shortcode', $content, $snippet, $atts, $original_atts ); } /** * Converts a value and key into an HTML attribute pair. * * @param string $value Attribute value. * @param string $key Attribute name. * * @return void */ private static function create_attribute_pair( string &$value, string $key ) { $value = sprintf( '%s="%s"', sanitize_key( $key ), esc_attr( $value ) ); } /** * Render the source code of a given snippet * * @param Snippet $snippet Snippet object. * @param array $atts Shortcode attributes. * * @return string Shortcode content. */ private function render_snippet_source( Snippet $snippet, array $atts = [] ): string { $atts = array_merge( array( 'line_numbers' => false, 'highlight_lines' => '', ), $atts ); $language = 'css' === $snippet->type ? 'css' : ( 'js' === $snippet->type ? 'js' : 'php' ); $pre_attributes = array( 'id' => "code-snippet-source-$snippet->id", 'class' => 'code-snippet-source', ); $code_attributes = array( 'class' => "language-$language", ); if ( $atts['line_numbers'] ) { $code_attributes['class'] .= ' line-numbers'; $pre_attributes['class'] .= ' linkable-line-numbers'; } if ( $atts['highlight_lines'] ) { $pre_attributes['data-line'] = $atts['highlight_lines']; } $pre_attributes = apply_filters( 'code_snippets/prism_pre_attributes', $pre_attributes, $snippet, $atts ); $code_attributes = apply_filters( 'code_snippets/prism_code_attributes', $code_attributes, $snippet, $atts ); array_walk( $code_attributes, array( $this, 'create_attribute_pair' ) ); array_walk( $pre_attributes, array( $this, 'create_attribute_pair' ) ); $code = 'php' === $snippet->type ? "code" : $snippet->code; $output = sprintf( '
%s
', implode( ' ', $pre_attributes ), implode( ' ', $code_attributes ), esc_html( $code ) ); return apply_filters( 'code_snippets/render_source_shortcode', $output, $snippet, $atts ); } /** * Render the value of a source shortcode * * @param array $atts Shortcode attributes. * * @return string Shortcode content. */ public function render_source_shortcode( array $atts ): string { $atts = $this->convert_boolean_attribute_flags( $atts, [ 'network', 'line_numbers' ] ); $atts = shortcode_atts( array( 'id' => 0, 'snippet_id' => 0, 'network' => false, 'line_numbers' => false, 'highlight_lines' => '', ), $atts, self::SOURCE_SHORTCODE ); $id = 0 !== intval( $atts['snippet_id'] ) ? intval( $atts['snippet_id'] ) : intval( $atts['id'] ); if ( ! $id ) { return $this->invalid_id_warning( $id ); } $snippet = get_snippet( $id, (bool) $atts['network'] ); return $this->render_snippet_source( $snippet, $atts ); } }