Plugin Directory

Changeset 3245133


Ignore:
Timestamp:
02/23/2025 06:32:26 AM (2 weeks ago)
Author:
akirk
Message:

enable-mastodon-apps 1.2.0

Location:
enable-mastodon-apps/trunk
Files:
1 added
18 edited

Legend:

Unmodified
Added
Removed
  • enable-mastodon-apps/trunk/README.md

    r3243595 r3245133  
    77- Requires PHP: 7.4
    88- License: [GPLv2 or later](http://www.gnu.org/licenses/gpl-2.0.html)
    9 - Stable tag: 1.1.0
     9- Stable tag: 1.2.0
    1010
    1111Allow accessing your WordPress with Mastodon clients. Just enter your own blog URL as your instance.
     
    101101## Changelog
    102102
     103### 1.2.0
     104- Fixed Boost, Like and Comment notifications ([#216])
     105- Announce Initial and Changed App Settings ([#207], [#214])
     106- Added a Welcome message to your feed and explain the EMA plugin ([#210])
     107- Added missing types to notifications endpoint ([#215])
     108- Don't set any post formats as default ([#211])
     109- Updated Mastodon API Tester ([#209])
     110- Added a setting to disable status updates to be added to the feed ([#208])
     111- Added support for the OAuth2 Out of Band flow ([#206])
     112
    103113### 1.1.0
    104114- Add an Announcement CPT so that we can inform about the changed app settings ([#204])
     
    171181- Fix OAuth rewrite path ([#130])
    172182
     183[#216]: https://github.com/akirk/enable-mastodon-apps/pull/216
     184[#214]: https://github.com/akirk/enable-mastodon-apps/pull/214
     185[#215]: https://github.com/akirk/enable-mastodon-apps/pull/215
     186[#211]: https://github.com/akirk/enable-mastodon-apps/pull/211
     187[#210]: https://github.com/akirk/enable-mastodon-apps/pull/210
     188[#209]: https://github.com/akirk/enable-mastodon-apps/pull/209
     189[#208]: https://github.com/akirk/enable-mastodon-apps/pull/208
     190[#207]: https://github.com/akirk/enable-mastodon-apps/pull/207
     191[#206]: https://github.com/akirk/enable-mastodon-apps/pull/206
    173192[#204]: https://github.com/akirk/enable-mastodon-apps/pull/204
    174193[#203]: https://github.com/akirk/enable-mastodon-apps/pull/203
  • enable-mastodon-apps/trunk/enable-mastodon-apps.php

    r3243595 r3245133  
    44 * Plugin author: Alex Kirk
    55 * Plugin URI: https://github.com/akirk/enable-mastodon-apps
    6  * Version: 1.1.0
     6 * Version: 1.2.0
    77 *
    88 * Description: Allow accessing your WordPress with Mastodon clients. Just enter your own blog URL as your instance.
     
    2020defined( 'ABSPATH' ) || exit;
    2121define( 'ENABLE_MASTODON_APPS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
    22 define( 'ENABLE_MASTODON_APPS_VERSION', '1.1.0' );
     22define( 'ENABLE_MASTODON_APPS_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
     23define( 'ENABLE_MASTODON_APPS_VERSION', '1.2.0' );
    2324
    2425require __DIR__ . '/vendor/bshaffer/oauth2-server-php/src/OAuth2/Autoloader.php';
     
    7071);
    7172
    72 if ( is_admin() && version_compare( get_option( 'ema_plugin_version', ENABLE_MASTODON_APPS_VERSION ), '<' ) ) {
     73if ( is_admin() && version_compare( get_option( 'ema_plugin_version' ), ENABLE_MASTODON_APPS_VERSION, '<' ) ) {
    7374    add_action( 'admin_init', array( __NAMESPACE__ . '\Mastodon_Admin', 'upgrade_plugin' ) );
    7475}
  • enable-mastodon-apps/trunk/includes/class-comment-cpt.php

    r3158797 r3245133  
    7474
    7575    public function mastodon_api_in_reply_to_id( $post_id ) {
    76         $comment_id = $this->post_id_to_comment_id( $post_id );
     76        $comment_id = self::post_id_to_comment_id( $post_id );
    7777        if ( $comment_id ) {
    7878            return $comment_id;
     
    8181    }
    8282
    83     public function post_id_to_comment_id( $post_id ) {
     83    public static function post_id_to_comment_id( $post_id ) {
    8484        if ( get_post_type( $post_id ) !== self::CPT ) {
    8585            return null;
     
    153153            return;
    154154        }
    155         $comment_id = $this->post_id_to_comment_id( $post_id );
     155        $comment_id = self::post_id_to_comment_id( $post_id );
    156156        if ( ! $comment_id ) {
    157157            return;
  • enable-mastodon-apps/trunk/includes/class-mastodon-admin.php

    r3243595 r3245133  
    2020        add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
    2121        add_action( 'current_screen', array( $this, 'register_help' ) );
     22        add_filter( 'plugin_action_links_' . ENABLE_MASTODON_APPS_PLUGIN_BASENAME, array( $this, 'plugin_action_links' ) );
    2223    }
    2324
     
    108109    }
    109110
    110 
     111    public function plugin_action_links( $links ) {
     112        $links[] = '<a href="' . esc_url( admin_url( 'options-general.php?page=enable-mastodon-apps' ) ) . '">' . esc_html__( 'Settings', 'enable-mastodon-apps' ) . '</a>';
     113        return $links;
     114    }
    111115
    112116    public function process_admin() {
     
    214218            delete_option( 'mastodon_api_posting_cpt' );
    215219
    216             $supported_post_types = (array) \get_option( 'activitypub_support_post_types', array( 'post' ) );
    217             $supported_post_types[] = $default_ema_post_type;
    218             \update_option( 'activitypub_support_post_types', $supported_post_types );
     220            if ( defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) ) {
     221                $supported_post_types = (array) \get_option( 'activitypub_support_post_types', array( 'post' ) );
     222                if ( ! in_array( $default_ema_post_type, $supported_post_types, true ) ) {
     223                    $supported_post_types[] = $default_ema_post_type;
     224                    \update_option( 'activitypub_support_post_types', $supported_post_types );
     225                }
     226            }
    219227        } else {
    220             update_option( 'mastodon_api_posting_cpt', 'post' );
    221 
    222             $supported_post_types = (array) \get_option( 'activitypub_support_post_types', array( 'post' ) );
    223             if ( in_array( $default_ema_post_type, $supported_post_types, true ) ) {
    224                 $supported_post_types = array_diff( $supported_post_types, array( $default_ema_post_type ) );
    225                 \update_option( 'activitypub_support_post_types', $supported_post_types );
    226             }
     228            update_option( 'mastodon_api_posting_cpt', 'post', false );
     229
     230            if ( defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) ) {
     231                $supported_post_types = (array) \get_option( 'activitypub_support_post_types', array( 'post' ) );
     232                if ( in_array( $default_ema_post_type, $supported_post_types, true ) ) {
     233                    $supported_post_types = array_diff( $supported_post_types, array( $default_ema_post_type ) );
     234                    \update_option( 'activitypub_support_post_types', $supported_post_types );
     235                }
     236            }
     237        }
     238
     239        if ( isset( $_POST['mastodon_api_disable_ema_announcements'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
     240            delete_option( 'mastodon_api_disable_ema_announcements' );
     241        } else {
     242            update_option( 'mastodon_api_disable_ema_announcements', true, false );
     243        }
     244
     245        if ( isset( $_POST['mastodon_api_disable_ema_app_settings_changes'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
     246            delete_option( 'mastodon_api_disable_ema_app_settings_changes' );
     247        } else {
     248            update_option( 'mastodon_api_disable_ema_app_settings_changes', true, false );
    227249        }
    228250
     
    653675        }
    654676        $app->set_post_formats( $post_formats );
     677        $post_formats = $app->get_post_formats();
    655678
    656679        $post_types = array_flip(
     
    686709        }
    687710
    688         wp_insert_post(
    689             array(
    690                 'post_type'    => Mastodon_API::ANNOUNCE_CPT,
    691                 'post_title'   => __( 'Only Visible to You', 'enable-mastodon-apps' ),
    692                 'post_content' =>
    693                     sprintf(
    694                         // translators: %s: app name.
    695                         __( 'The settings for %s were changed as follows:', 'enable-mastodon-apps' ),
    696                         $app->get_client_name()
    697                     ) . PHP_EOL .
    698                     'Post Formats: ' . implode( ', ', $post_formats ) . PHP_EOL .
    699                     'Create Post Type: ' . $create_post_type . PHP_EOL .
    700                     'Post Types: ' . implode( ', ', array_keys( $view_post_types ) ),
    701                 'post_status'  => 'publish',
    702                 'meta_input'   => array(
    703                     'ema_app_id' => $app->get_client_id(),
    704                 ),
    705             )
    706         );
     711        if ( isset( $_POST['disable_blocks'] ) ) {
     712            $app->set_disable_blocks( true );
     713        } else {
     714            $app->set_disable_blocks( false );
     715        }
     716
     717        $app->post_current_settings();
    707718    }
    708719
     
    735746        }
    736747
     748        if ( ! get_option( 'mastodon_api_disable_ema_announcements' ) ) {
     749            if ( ! $old_version ) {
     750                $title = __( 'Welcome to Enable Mastodon Apps!', 'enable-mastodon-apps' );
     751                $content = __( 'This is a message from the Enable Mastodon Apps plugin that you have installed on your WordPress.', 'enable-mastodon-apps' );
     752                $content .= PHP_EOL . '<br>';
     753                $content .= __( 'The plugin allows you to see all posts on your site inside this app.', 'enable-mastodon-apps' );
     754                if ( ! defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) ) {
     755                    // When standalone, we want to post to your WordPress.
     756                    update_option( 'mastodon_api_posting_cpt', 'post', false );
     757                    $content .= __( 'If you submit a status, it will be posted to your site.', 'enable-mastodon-apps' );
     758                    $content .= ' ' . __( "Be aware that this means that it will also be shown in your site's feed.", 'enable-mastodon-apps' );
     759                } else {
     760                    $default_ema_post_type = apply_filters( 'mastodon_api_default_post_type', \Enable_Mastodon_Apps\Mastodon_API::POST_CPT );
     761                    $supported_post_types = (array) \get_option( 'activitypub_support_post_types', array( 'post' ) );
     762                    if ( ! in_array( $default_ema_post_type, $supported_post_types, true ) ) {
     763                        $supported_post_types[] = $default_ema_post_type;
     764                        \update_option( 'activitypub_support_post_types', $supported_post_types );
     765                    }
     766                    $content .= __( 'If you submit a status, it will be posted so that it is hidden from your site (by using a custom post type).', 'enable-mastodon-apps' );
     767                    $content .= ' ';
     768                    $content .= __( 'By means of the ActivityPub plugin that you also have installed, it will still be federated to your followers.', 'enable-mastodon-apps' );
     769                }
     770                $content .= ' ';
     771                $content .= __( 'This can be changed individually per app (see the link below).', 'enable-mastodon-apps' );
     772                $content .= PHP_EOL . '<br>';
     773                $content .= __( 'How it works: By providing the same API that Mastodon offers, it brings two worlds together that were not really designed for this interoperability. Thus, while it typically functions well, you might still experience some unexpected behavior.', 'enable-mastodon-apps' );
     774                $content .= ' ';
     775                // translators: %s is a clickable URL.
     776                $content .= make_clickable( sprintf( __( 'Please visit %s to get help in such a case.', 'enable-mastodon-apps' ), 'https://github.com/akirk/enable-mastodon-apps/issues' ) );
     777                $content .= PHP_EOL . '<br>';
     778                // translators: %s is a URL.
     779                $content .= sprintf( __( 'If you enjoy using this plugin, please let us know at the <a href=%s>EMA WordPress.org plugin page</a>.', 'enable-mastodon-apps' ), '"https://wordpress.org/plugins/enable-mastodon-apps/"' );
     780
     781                wp_insert_post(
     782                    array(
     783                        'post_type'    => Mastodon_API::ANNOUNCE_CPT,
     784                        'post_title'   => $title,
     785                        'post_status'  => 'publish',
     786                        'post_content' => $content,
     787
     788                    )
     789                );
     790            } else {
     791                $readme = file_get_contents( ENABLE_MASTODON_APPS_PLUGIN_DIR . 'README.md' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
     792                $changelog = substr( $readme, strpos( $readme, '## Changelog' ) );
     793                $first_section = strpos( $changelog, '###' );
     794                $changelog = substr( $changelog, $first_section, strpos( $changelog, '###', $first_section + 1 ) - $first_section );
     795
     796                $changelog = preg_replace( '/\[#(\d+)\]/', '<a href="https://github.com/akirk/enable-mastodon-apps/pull/\1">#\1</a>', $changelog );
     797                list( $headline, $changes ) = explode( PHP_EOL, $changelog, 2 );
     798
     799                // translators: %s: version number.
     800                $title = sprintf( __( "What's new in EMA %s?", 'enable-mastodon-apps' ), trim( $headline, ' #' ) );
     801
     802                $posts = get_posts(
     803                    array(
     804                        'post_type'      => Mastodon_API::ANNOUNCE_CPT,
     805                        'posts_per_page' => 1,
     806                        'post_status'    => 'publish',
     807                        'title'          => $title,
     808                    )
     809                );
     810                if ( ! $posts ) {
     811                    $changes = wp_kses( $changes, array( 'a' => array( 'href' => true ) ) );
     812
     813                    wp_insert_post(
     814                        array(
     815                            'post_type'    => Mastodon_API::ANNOUNCE_CPT,
     816                            'post_title'   => $title,
     817                            'post_status'  => 'publish',
     818                            'post_content' => $changes,
     819                        )
     820                    );
     821                }
     822            }
     823        }
     824
    737825        if ( version_compare( $old_version, '1.0.0', '<' ) ) {
    738826            // If the friends plugin is installed, add the friends post type to the list of post types that can be viewed.
  • enable-mastodon-apps/trunk/includes/class-mastodon-api.php

    r3243595 r3245133  
    7474        add_filter( 'template_include', array( $this, 'log_404s' ) );
    7575        add_filter( 'rest_json_encode_options', array( $this, 'rest_json_encode_options' ), 10, 2 );
    76         add_action( 'default_option_mastodon_api_default_post_formats', array( $this, 'default_option_mastodon_api_default_post_formats' ) );
    7776        add_filter( 'rest_request_before_callbacks', array( $this, 'rest_request_before_callbacks' ), 10, 3 );
    7877        add_filter( 'rest_authentication_errors', array( $this, 'rest_authentication_errors' ) );
     
    193192            ),
    194193            'description'  => __( 'Posted through a Mastodon app.', 'enable-mastodon-apps' ),
    195             'public'       => ! get_option( 'mastodon_api_posting_cpt' ),
     194            'public'       => ! get_option( 'mastodon_api_posting_cpt' ) || ( defined( 'WP_DEBUG' ) && WP_DEBUG ),
    196195            'show_in_rest' => false,
    197196            'rewrite'      => false,
     
    208207            ),
    209208            'description'  => __( 'Announcement by the Enable Mastodon Apps plugin.', 'enable-mastodon-apps' ),
    210             'public'       => false,
     209            'public'       => defined( 'WP_DEBUG' ) && WP_DEBUG,
    211210            'show_in_rest' => false,
    212211            'rewrite'      => false,
     
    648647                            'type' => 'string',
    649648                            'enum' => array(
    650                                 'mention',
    651                                 'status',
    652                                 'reblog',
     649                                'admin.report',
     650                                'admin.sign_up',
     651                                'favourite',
    653652                                'follow',
    654653                                'follow_request',
    655                                 'favourite',
     654                                'mention',
     655                                'pleroma:emoji_reaction',
    656656                                'poll',
     657                                'reaction',
     658                                'reblog',
     659                                'severed_relationship',
     660                                'status',
    657661                                'update',
    658                                 'admin.sign_up',
    659                                 'admin.report',
    660                                 'severed_relationship',
    661662                            ),
    662663                        ),
     
    18251826
    18261827    /**
    1827      * Set the default post format.
    1828      *
    1829      * @param mixed $post_formats The default value to return if the option does not exist
    1830      *                        in the database.
    1831      *
    1832      * @return     array   The potentially modified default value.
    1833      */
    1834     public function default_option_mastodon_api_default_post_formats( $post_formats ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
    1835         return array(
    1836             'standard',
    1837         );
    1838     }
    1839 
    1840     /**
    18411828     * Converts param validation errors to error codes expected by Mastodon apps.
    18421829     *
  • enable-mastodon-apps/trunk/includes/class-mastodon-app.php

    r3243595 r3245133  
    8686        $query_args = $this->get_query_args();
    8787        if ( ! isset( $query_args['post_formats'] ) || ! is_array( $query_args['post_formats'] ) ) {
    88             return get_option( 'mastodon_api_default_post_formats', array() );
     88            return array();
     89        }
     90
     91        if ( array_keys( get_post_format_slugs() ) === $query_args['post_formats'] ) {
     92            return array();
    8993        }
    9094
     
    9397
    9498    public function get_admin_page() {
    95         return add_query_arg( 'app', $this->term->slug, admin_url( 'admin.php?page=enable-mastodon-apps' ) );
     99        return add_query_arg( 'app', $this->term->slug, admin_url( 'options-general.php?page=enable-mastodon-apps' ) );
    96100    }
    97101
     
    228232        }
    229233        update_term_meta( $this->term->term_id, 'last_used', time() );
     234    }
     235
     236    /**
     237     * Posts current settings as an announcement just for this app.
     238     *
     239     * @param      string $title  The title.
     240     * @param      string $intro  The intro text.
     241     *
     242     * @return     int|null  The post ID.
     243     */
     244    public function post_current_settings( string $title = '', string $intro = '' ) {
     245        if ( get_option( 'mastodon_api_disable_ema_app_settings_changes' ) ) {
     246            return null;
     247        }
     248
     249        if ( ! $title ) {
     250            $title = sprintf(
     251                // translators: %s: app name.
     252                __( 'Settings for %s changed', 'enable-mastodon-apps' ),
     253                $this->get_client_name()
     254            );
     255        }
     256
     257        if ( ! $intro ) {
     258            $intro = __( 'The current settings for this app are:', 'enable-mastodon-apps' );
     259        }
     260        $content = $intro;
     261
     262        $post_formats = $this->get_post_formats();
     263        $t = PHP_EOL . __( 'Post Formats', 'enable-mastodon-apps' ) . ': ';
     264        foreach ( get_post_format_strings() as $slug => $name ) {
     265            if ( ! in_array( $slug, $post_formats, true ) ) {
     266                continue;
     267            }
     268            $content .= $t . $name;
     269            $t = ', ';
     270        }
     271        if ( ', ' !== $t ) {
     272            $content .= $t . __( 'All' ); // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
     273        }
     274
     275        $content .= PHP_EOL . _x( 'Create new posts as', 'select post type', 'enable-mastodon-apps' ) . ': ';
     276        $content .= get_post_type_object( $this->get_create_post_type() )->labels->singular_name;
     277        $t = PHP_EOL . __( 'Show these post types', 'enable-mastodon-apps' ) . ': ';
     278        foreach ( $this->get_view_post_types() as $post_type ) {
     279            if ( in_array( $post_type, array( Mastodon_API::ANNOUNCE_CPT, Mastodon_API::POST_CPT ), true ) ) {
     280                continue;
     281            }
     282            $content .= $t . get_post_type_object( $post_type )->labels->name;
     283            $t = ', ';
     284        }
     285
     286        if ( $this->get_disable_blocks() ) {
     287            $content .= PHP_EOL . __( 'Automatic conversion to blocks is disabled', 'enable-mastodon-apps' );
     288        }
     289
     290        $previous_posts = get_posts(
     291            array(
     292                'post_type'   => Mastodon_API::ANNOUNCE_CPT,
     293                'post_status' => 'publish',
     294                'meta_query'  => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
     295                    array(
     296                        'key'   => 'ema_app_id',
     297                        'value' => $this->get_client_id(),
     298                    ),
     299                ),
     300            )
     301        );
     302
     303        foreach ( $previous_posts as $previous_post ) {
     304            wp_delete_post( $previous_post->ID );
     305        }
     306
     307        return wp_insert_post(
     308            array(
     309                'post_type'    => Mastodon_API::ANNOUNCE_CPT,
     310                'post_title'   => $title,
     311                'post_content' => nl2br( trim( $content ) ),
     312                'post_status'  => 'publish',
     313                'meta_input'   => array(
     314                    'ema_app_id' => $this->get_client_id(),
     315                ),
     316            )
     317        );
    230318    }
    231319
     
    668756        );
    669757
    670         $post_formats = get_option( 'mastodon_api_default_post_formats', array() );
    671758        /**
    672759         * Post formats to be enabled for new apps.
     
    684771         * ```
    685772         */
    686         $post_formats = apply_filters( 'mastodon_api_new_app_post_formats', $post_formats, $app_metadata );
     773        $post_formats = apply_filters( 'mastodon_api_new_app_post_formats', array(), $app_metadata );
    687774        $app_metadata['query_args'] = array( 'post_formats' => $post_formats );
    688775
     
    722809        }
    723810
    724         return new self( $term );
     811        $app = new self( $term );
     812        $app->post_current_settings(
     813            sprintf(
     814                // translators: %s: app name.
     815                __( 'App %s created', 'enable-mastodon-apps' ),
     816                $client_name
     817            ),
     818            __( 'This app was created with the following settings:', 'enable-mastodon-apps' )
     819        );
     820        return $app;
    725821    }
    726822}
  • enable-mastodon-apps/trunk/includes/class-mastodon-oauth.php

    r3129164 r3245133  
    1212use OAuth2\Server;
    1313use OAuth2\Request;
    14 use OAuth2\Response;
     14use Enable_Mastodon_Apps\OAuth2\Response;
    1515
    1616/**
  • enable-mastodon-apps/trunk/includes/handler/class-handler.php

    r3240587 r3245133  
    128128        }
    129129
    130         krsort( $statuses );
     130        usort(
     131            $statuses,
     132            function ( $a, $b ) {
     133                return $b->created_at->getTimestamp() - $a->created_at->getTimestamp();
     134            }
     135        );
    131136
    132137        $response = new \WP_REST_Response( array_values( $statuses ) );
  • enable-mastodon-apps/trunk/includes/handler/class-notification.php

    r3129164 r3245133  
    4848        foreach ( $notifications as $notification ) {
    4949            if ( $notification['status'] ) {
    50                 wp_set_object_terms( $notification['status']['id'], $notification_dismissed_tag, 'post_tag', true );
     50                wp_set_object_terms( $notification['status']->id, $notification_dismissed_tag, 'post_tag', true );
    5151            }
    5252        }
     
    6868            }
    6969            if ( $notification['status'] ) {
    70                 wp_set_object_terms( $notification['status']['id'], $notification_dismissed_tag, 'post_tag', true );
     70                wp_set_object_terms( $notification['status']->id, $notification_dismissed_tag, 'post_tag', true );
    7171            }
    7272        }
     
    9191        }
    9292
    93         return new WP_Error( 'notification_not_found', __( 'Notification not found.', 'enable-mastodon-apps' ) );
     93        return new \WP_Error( 'notification_not_found', __( 'Notification not found.', 'enable-mastodon-apps' ) );
    9494    }
    9595
     
    159159            }
    160160            foreach ( get_posts( $args ) as $post ) {
     161                $comment_id = Comment_CPT::post_id_to_comment_id( $post->ID );
    161162                $account = apply_filters( 'mastodon_api_account', null, $post->post_author, null, $post );
    162                 $status  = apply_filters( 'mastodon_api_status', null, $post->ID, array() );
     163                switch ( get_comment_type( $comment_id ) ) {
     164                    case 'like':
     165                        $type = 'like';
     166                        $status  = apply_filters( 'mastodon_api_status', null, $post->post_parent, array() );
     167                        break;
     168                    case 'repost':
     169                        $type = 'reblog';
     170                        $status  = apply_filters( 'mastodon_api_status', null, $post->post_parent, array() );
     171                        break;
     172                    default:
     173                        $type = 'mention';
     174                        $status  = apply_filters( 'mastodon_api_status', null, $post->ID, array() );
     175                }
    163176                if ( $account && $status ) {
    164177                    $notifications[] = $this->get_notification_array(
    165                         'mention',
     178                        $type,
    166179                        mysql2date( 'Y-m-d\TH:i:s.000P', $post->post_date, false ),
    167180                        $account,
     
    188201        $c   = $limit;
    189202        foreach ( $notifications as $notification ) {
     203            if ( ! $notification ) {
     204                continue;
     205            }
    190206            if ( $max_id ) {
    191207                if ( strval( $notification['id'] ) >= strval( $max_id ) ) {
  • enable-mastodon-apps/trunk/includes/handler/class-status.php

    r3243595 r3245133  
    1010namespace Enable_Mastodon_Apps\Handler;
    1111
    12 use Enable_Mastodon_Apps\Entity\Entity;
    1312use Enable_Mastodon_Apps\Handler\Handler;
     13use Enable_Mastodon_Apps\Comment_CPT;
    1414use Enable_Mastodon_Apps\Mastodon_API;
    1515use Enable_Mastodon_Apps\Mastodon_App;
     
    133133        if ( Mastodon_API::ANNOUNCE_CPT === $post->post_type ) {
    134134            $meta = get_post_meta( $post->ID, 'ema_app_id', true );
    135             if ( $meta ) {
    136                 $app = Mastodon_App::get_current_app();
    137                 if ( ! $app || $app->get_client_id() !== $meta ) {
    138                     return null;
    139                 }
     135            $app = Mastodon_App::get_current_app();
     136            if ( $meta && ( ! $app || $app->get_client_id() !== $meta ) ) {
     137                return null;
     138            }
     139
     140            // translators: %s: settings page URL.
     141            $post->post_content = trim( $post->post_content ) .
     142                '<br>' . PHP_EOL . '<br>' . PHP_EOL .
     143                // translators: %s: settings page URL.
     144                sprintf( __( 'This message has been added by the EMA plugin. You can disable these messages <a href=%s>in the settings</a>.', 'enable-mastodon-apps' ), '"' . esc_url( admin_url( 'options-general.php?page=enable-mastodon-apps&tab=settings' ) ) . '"' );
     145            if ( $app ) {
     146                // translators: %s: settings page URL.
     147                $post->post_content .= ' ' . sprintf( __( 'Change the <a href=%s>settings for this app here</a>.', 'enable-mastodon-apps' ), '"' . esc_url( admin_url( 'options-general.php?page=enable-mastodon-apps&app=' . $app->get_client_id() ) ) . '"' );
    140148            }
    141149        }
     
    198206     * @param int|null   $min_id Optional minimum status ID.
    199207     * @param int|null   $max_id Optional maximum status ID.
    200      * @return array
     208     * @return WP_REST_Response The statuses as a REST response.
    201209     */
    202     public function api_statuses( ?array $statuses, array $args, ?int $min_id = null, ?int $max_id = null ): \WP_REST_Response {
     210    public function api_statuses( ?array $statuses, array $args, ?int $min_id = null, ?int $max_id = null ): WP_REST_Response {
    203211        if ( $statuses ) {
    204             if ( ! $statuses instanceof \WP_REST_Response ) {
    205                 $statuses = new \WP_REST_Response( array_values( $statuses ) );
     212            if ( ! $statuses instanceof WP_REST_Response ) {
     213                $statuses = new WP_REST_Response( array_values( $statuses ) );
    206214            }
    207215            return $statuses;
     
    217225    public function api_statuses_ensure_numeric_id( $statuses ) {
    218226        $response = null;
    219         if ( $statuses instanceof \WP_REST_Response ) {
     227        if ( $statuses instanceof WP_REST_Response ) {
    220228            $response = $statuses;
    221229            $statuses = $response->data;
  • enable-mastodon-apps/trunk/includes/oauth2/class-authenticate-handler.php

    r3243595 r3245133  
    1212use Enable_Mastodon_Apps\Mastodon_App;
    1313use OAuth2\Request;
    14 use OAuth2\Response;
    1514
    1615/**
     
    209208
    210209    private function get_cancel_url( Request $request ) {
     210        if ( substr( $request->query( 'redirect_uri' ), 0, 25 ) === 'urn:ietf:wg:oauth:2.0:oob' ) {
     211            return home_url( '/' );
     212        }
     213
    211214        return add_query_arg(
    212215            array(
  • enable-mastodon-apps/trunk/includes/oauth2/class-authorize-handler.php

    r3243595 r3245133  
    1111
    1212use OAuth2\Request;
    13 use OAuth2\Response;
    1413use OAuth2\Server as OAuth2Server;
    1514
  • enable-mastodon-apps/trunk/includes/oauth2/class-mastodon-app-storage.php

    r3240587 r3245133  
    104104            );
    105105
    106             $post_formats = get_option( 'mastodon_api_default_post_formats', array() );
    107             $post_formats = apply_filters( 'mastodon_api_new_app_post_formats', $post_formats, $app_metadata );
     106            $post_formats = apply_filters( 'mastodon_api_new_app_post_formats', array(), $app_metadata );
    108107            $app_metadata['query_args'] = array( 'post_formats' => $post_formats );
    109108
  • enable-mastodon-apps/trunk/includes/oauth2/class-revokation-handler.php

    r3035768 r3245133  
    1111
    1212use OAuth2\Request;
    13 use OAuth2\Response;
    1413use OAuth2\Server as OAuth2Server;
    1514
  • enable-mastodon-apps/trunk/includes/oauth2/class-token-handler.php

    r3129164 r3245133  
    1111
    1212use OAuth2\Request;
    13 use OAuth2\Response;
    1413use OAuth2\Server as OAuth2Server;
    1514
  • enable-mastodon-apps/trunk/templates/app.php

    r3243595 r3245133  
    2929    )
    3030);
     31$app_post_formats = $app->get_post_formats();
    3132?>
    3233<div class="enable-mastodon-apps-settings enable-mastodon-apps-registered-apps-page <?php echo $args['enable_debug'] ? 'enable-debug' : 'disable-debug'; ?>">
     
    117118                        <fieldset>
    118119                        <?php foreach ( get_post_format_strings() as $format => $label ) : ?>
    119                             <label><input type="checkbox" name="post_formats[]" value="<?php echo esc_attr( $format ); ?>"<?php checked( in_array( $format, $app->get_post_formats(), true ) ); ?> /> <?php echo esc_html( $label ); ?></label>
     120                            <label><input type="checkbox" name="post_formats[]" value="<?php echo esc_attr( $format ); ?>"<?php checked( in_array( $format, $app_post_formats, true ) || empty( $app_post_formats ) ); ?> /> <?php echo esc_html( $label ); ?></label>
    120121                        <?php endforeach; ?>
    121122                        </fieldset>
  • enable-mastodon-apps/trunk/templates/settings.php

    r3243595 r3245133  
    7474                </tr>
    7575                <tr>
     76                    <th scope="row"><?php esc_html_e( 'Status Messages', 'enable-mastodon-apps' ); ?></th>
     77                    <td>
     78                        <p class="description"><?php esc_html_e( 'Allow this plugin to inform you by adding a status to your feed:', 'enable-mastodon-apps' ); ?></p>
     79                        <fieldset>
     80                            <label for="mastodon_api_disable_ema_announcements">
     81                                <input name="mastodon_api_disable_ema_announcements" type="checkbox" id="mastodon_api_disable_ema_announcements" value="1" <?php checked( ! get_option( 'mastodon_api_disable_ema_announcements' ) ); ?> />
     82                                <span>
     83                                    <?php
     84                                    // translators: Changelog entries won't be translated so they will appear in English.
     85                                    esc_html_e( 'When it is updated to a new version and list the changes (in English).', 'enable-mastodon-apps' );
     86                                    ?>
     87                            </span>
     88                            </label>
     89
     90                            <label for="mastodon_api_disable_ema_app_settings_changes">
     91                                <input name="mastodon_api_disable_ema_app_settings_changes" type="checkbox" id="mastodon_api_disable_ema_app_settings_changes" value="1" <?php checked( ! get_option( 'mastodon_api_disable_ema_app_settings_changes' ) ); ?> />
     92                                <span><?php esc_html_e( "When changes are made to specific app's settings (only visible in the app's feed).", 'enable-mastodon-apps' ); ?></span>
     93                            </label>
     94                        </fieldset>
     95                    </td>
     96                </tr>
     97                <tr>
    7698                    <th scope="row"><?php esc_html_e( 'Debugging', 'enable-mastodon-apps' ); ?></th>
    7799                    <td>
  • enable-mastodon-apps/trunk/tester.html

    r3157710 r3245133  
    2424        }
    2525
    26         div.api-endpoint {
     26        div.iframe-holder {
     27            position: absolute;
     28            background-color: white;
     29            border: 1px solid black;
     30            padding: 10px;
     31            z-index: 1000;
     32        }
     33        div.iframe-holder iframe {
     34            border: 0;
     35            width: 40em;
     36        }
     37        div.iframe-holder button {
     38            position: absolute;
     39            top: 0;
     40            right: 0;
     41            background-color: white;
     42            border: 0;
     43            cursor: pointer;
     44
     45        }
     46
     47        li.api-endpoint {
    2748            cursor: pointer;
    2849            color: blue;
    2950            text-decoration: underline;
    30         }
    31 
    32         #api-endpoints>div {
     51            padding-left: .5em;
     52        }
     53
     54        #api-endpoints ul {
     55            list-style: none;
     56            padding-left: 0;
     57        }
     58        #api-endpoints li {
    3359            font-weight: bold;
    3460            margin-bottom: 10px;
     
    129155            border: 1px solid #aaa;
    130156        }
     157        input#api-custom-endpoint {
     158            width: 40em;
     159        }
    131160        button#send-api-custom-endpoint {
    132161            font-size: .9em;
     
    228257            <br />
    229258
    230             <input type="reset" id="reset"> <input type="reset" id="delete-local" value="Clear all data">
     259            <input type="reset" id="reset"> <input type="reset" id="delete-local2" value="Clear all data">
    231260        </div>
    232261    </details>
     
    234263    <div id="api-endpoints">
    235264        <h2>Endpoints</h2>
    236         <p>Clicking these will send a request to the API and display the response in the box below.</p>
    237         <div class="api-endpoint">/api/v1/accounts/verify_credentials</div>
    238         <div class="api-endpoint">/api/v1/accounts/relationships</div>
    239         <div class="api-endpoint">/api/v1/timelines/home</div>
    240         <div class="api-endpoint">/api/v1/notifications</div>
     265        <p>Clicking these will send a request to the API and display the response in the box below. Shift-click to remove an item.</p>
     266        <ul>
     267        </ul>
    241268        <div><input type="text" id="api-custom-endpoint" value="/api/v1/accounts/1/statuses"> <button id="send-api-custom-endpoint">Send</button></div>
    242269        <h2>Endpoints with parameters</h2>
     
    261288    <script>
    262289        function logRequest(data) {
     290            document.querySelectorAll('div.iframe-holder').forEach( function( div ) {
     291                div.remove();
     292            } );
     293
    263294            const div = document.createElement('div');
    264295            const timestamp = document.createElement('tt');
     
    405436            document.getElementById('authorization-status').style.display = 'block';
    406437            document.getElementById('detailsblock').style.display = 'block';
    407             document.getElementById('authorization-status').textContent = 'Authorized.';
     438            document.getElementById('authorization-status').textContent = 'Authorized with ' + localStorage.getItem('baseURL');
     439
    408440            document.getElementById('authorize').textContent = 'Re-Authorize';
    409441        }
     
    506538        });
    507539
     540        document.getElementById('delete-local2').addEventListener('click', function () {
     541            localStorage.clear();
     542            location.reload();
     543        });
    508544
    509545        document.getElementById('reset').addEventListener('click', function () {
     
    534570                history.replaceState(null, null, window.location.pathname + (urlParams.toString() ? '?' + urlParams.toString() : ''));
    535571            }
     572
     573            const customEndpoints = JSON.parse( localStorage.getItem( 'customEndpoints' ) ) || [];
     574            if ( ! customEndpoints.length ) {
     575                customEndpoints.push( '/api/v1/accounts/verify_credentials' );
     576                customEndpoints.push( '/api/v1/accounts/relationships?id[][email protected]' );
     577                customEndpoints.push( '/api/v1/timelines/home' );
     578                customEndpoints.push( '/api/v1/notifications' );
     579                localStorage.setItem( 'customEndpoints', JSON.stringify( customEndpoints ) );
     580            };
     581            const apiEndpoints = document.getElementById('api-endpoints').querySelector('ul');
     582            customEndpoints.forEach( function( endpoint ) {
     583                const li = document.createElement('li');
     584                li.className = 'api-endpoint';
     585                li.textContent = endpoint;
     586                apiEndpoints.appendChild( li );
     587            } );
    536588
    537589            const requestLog = document.getElementById('request-log');
     
    579631            return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    580632        }
    581 
     633        let showPreview = false;
    582634
    583635        document.addEventListener("mouseover", (event) => {
     
    590642
    591643                link.appendChild(img);
     644            }
     645            if (event.target.classList.contains('string') && event.target.textContent.match( /</) ) {
     646                if ( event.target.querySelector('div.iframe-holder') ) {
     647                    return;
     648                }
     649                if ( showPreview ) {
     650                    clearTimeout( showPreview );
     651                }
     652                showPreview = setTimeout( function() {
     653                    let status = event.target.textContent.substr(1, event.target.textContent.length - 2).replace( /\\"/g, '"' ).replace( /\\n/g, "\n" ).replace( /href=/g, 'target="_blank" href=' );
     654                    const iframe = document.createElement('iframe');
     655                    iframe.setAttribute('sandbox', 'allow-same-origin allow-popups');
     656                    iframe.srcdoc = '<style>body { font-family: sans-serif; line-height: 1.2; white-space: preserve-breaks; } a:any-link { color: #098658; }</style>' + status;
     657                    const div = document.createElement('div');
     658                    div.style.left = event.target.offsetLeft + 'px';
     659                    div.style.top = (event.target.offsetTop + 20 ) + 'px';
     660                    div.className = 'iframe-holder';
     661                    div.appendChild(iframe);
     662                    const close = document.createElement('button');
     663                    close.textContent = 'Close';
     664                    close.addEventListener('click', function() {
     665                        div.remove();
     666                    });
     667                    div.appendChild(close);
     668
     669                    event.target.appendChild(div);
     670                }, 500 );
    592671            }
    593672        });
     
    623702        }
    624703
     704        document.addEventListener('keyup', function (event) {
     705            if ( event.key === 'Enter' ) {
     706                if ( event.target.id === 'api-custom-endpoint' ) {
     707                    document.getElementById('send-api-custom-endpoint').click();
     708                    return;
     709                }
     710
     711                if ( event.target.tagName === 'INPUT' ) {
     712                    const endpoint = event.target.closest('details').querySelector('.api-endpoint');
     713                    if ( endpoint ) {
     714                        endpoint.click();
     715                    }
     716                }
     717            }
     718        } );
     719
     720        document.addEventListener('mousemove', function (event) {
     721            if (event.target.classList.contains('api-endpoint') ) {
     722                 if ( event.shiftKey ) {
     723                    event.target.style.textDecoration = 'line-through';
     724                    event.target.style.color = 'red';
     725                 } else {
     726                    event.target.style.textDecoration = null;
     727                    event.target.style.color = null;
     728                 }
     729            }
     730        });
     731        document.addEventListener('mouseout', function (event) {
     732            if (event.target.classList.contains('api-endpoint') ) {
     733                    event.target.style.textDecoration = null;
     734                    event.target.style.color = null;
     735            }
     736        });
     737
    625738        document.addEventListener('click', function (event) {
    626739            let endpoint = false;
     
    628741            let submitValues = false;
    629742            if (event.target.classList.contains('api-endpoint')) {
     743                if ( event.shiftKey ) {
     744                    event.target.remove();
     745                    const customEndpoints = JSON.parse( localStorage.getItem( 'customEndpoints' ) ) || [];
     746                    const index = customEndpoints.indexOf( event.target.textContent );
     747                    if ( index > -1 ) {
     748                        customEndpoints.splice( index, 1 );
     749                        localStorage.setItem( 'customEndpoints', JSON.stringify( customEndpoints ) );
     750                    }
     751                    return;
     752                }
    630753                endpoint = event.target.dataset.endpoint || event.target.textContent;
     754                document.getElementById('api-custom-endpoint').value = endpoint;
    631755                method = event.target.dataset.method || 'GET';
    632756                if ( event.target.tagName === 'BUTTON' ) {
     
    635759            } else if (event.target.id === 'send-api-custom-endpoint') {
    636760                endpoint = document.getElementById('api-custom-endpoint').value;
     761                if ( '/' !== endpoint.substr( 0, 1 ) ) {
     762                    endpoint = '/' + endpoint;
     763                }
     764                let endpointExists = false;
     765                document.querySelectorAll('#api-endpoints li.api-endpoint' ).forEach( function( li ) {
     766                    if ( li.textContent === endpoint ) {
     767                        endpointExists = true;
     768                    }
     769                } );
     770                if ( ! endpointExists ) {
     771                    const li = document.createElement('li');
     772                    li.className = 'api-endpoint';
     773                    li.textContent = endpoint;
     774                    document.getElementById('api-endpoints').querySelector('ul').appendChild(li);
     775                    const customEndpoints = JSON.parse( localStorage.getItem( 'customEndpoints' ) ) || [];
     776                    if ( ! customEndpoints.includes( endpoint ) ) {
     777                        customEndpoints.push( endpoint );
     778                        localStorage.setItem( 'customEndpoints', JSON.stringify( customEndpoints ) );
     779                    }
     780                }
    637781                method = 'GET';
    638782            }
Note: See TracChangeset for help on using the changeset viewer.