Plugin Directory

Changeset 2651566


Ignore:
Timestamp:
01/01/2022 03:07:40 PM (4 years ago)
Author:
seindal
Message:

Translateable strings marked, and more consistent spacing.

Location:
planetplanet/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • planetplanet/trunk/planetplanet-cli.php

    r2650916 r2651566  
    4242     */
    4343
    44     public function list_feeds($args, $assoc) {
     44    public function list_feeds( $args, $assoc ) {
    4545        $links = get_bookmarks();
    4646
    47         if (isset($assoc['match'])) {
     47        if ( isset( $assoc['match'] ) ) {
    4848            $s = $assoc['match'];
    49             $links = array_filter($links, function ($link) use ($s) {
    50                 if (stripos($link->link_name, $s) !== false) return true;
    51                 if (stripos($link->link_url,  $s) !== false) return true;
    52                 if (stripos($link->link_rss,  $s) !== false) return true;
     49            $links = array_filter( $links, function ( $link ) use ( $s ) {
     50                if ( stripos( $link->link_name, $s ) !== false ) return true;
     51                if ( stripos( $link->link_url,  $s ) !== false ) return true;
     52                if ( stripos( $link->link_rss,  $s ) !== false ) return true;
    5353                return false;
    54             });
     54            } );
    5555        }
    5656
     
    7575     */
    7676
    77     public function update_all($args, $assoc) {
    78         global $planetplanet;
    79 
    80         if (isset($assoc['log-level']))
    81             $planetplanet->set_loglevel($assoc['log-level']);
     77    public function update_all( $args, $assoc ) {
     78        global $planetplanet;
     79
     80        if ( isset( $assoc['log-level'] ) )
     81            $planetplanet->set_loglevel( $assoc['log-level'] );
    8282
    8383        $planetplanet->update_all_feeds();
    84         WP_CLI::success( 'done.' );
     84        WP_CLI::success( __('Done.', 'planetplanet') );
    8585    }
    8686
     
    107107     */
    108108
    109     public function update($args, $assoc) {
    110         global $planetplanet;
    111 
    112         if (isset($assoc['log-level']))
    113             $planetplanet->set_loglevel($assoc['log-level']);
    114 
    115         foreach ($args as $arg) {
    116             $link = get_bookmark((int)$arg);
    117             if (isset($link)) {
    118                 $planetplanet->update_feed($link);
    119                 WP_CLI::success( sprintf( 'Updated feed %d %s', $link->link_id, $link->link_name) );
    120             } else
    121                 WP_CLI::warning( sprintf( 'No feed with ID %s', $arg) );
     109    public function update( $args, $assoc ) {
     110        global $planetplanet;
     111
     112        if ( isset( $assoc['log-level'] ) )
     113            $planetplanet->set_loglevel( $assoc['log-level']);
     114
     115        foreach ( $args as $arg ) {
     116            $link = get_bookmark( (int)$arg );
     117            if ( isset( $link ) ) {
     118                $planetplanet->update_feed( $link );
     119                WP_CLI::success( sprintf( __('Updated feed %d %s', 'planetplanet'), $link->link_id, $link->link_name) );
     120            } else {
     121                WP_CLI::warning( sprintf( __('No feed with ID %s', 'planetplanet'), $arg) );
     122            }
    122123        }
    123124    }
     
    140141     */
    141142
    142     public function purge($args, $assoc) {
    143         global $planetplanet;
    144 
    145         if (isset($assoc['log-level']))
    146             $planetplanet->set_loglevel($assoc['log-level']);
     143    public function purge( $args, $assoc ) {
     144        global $planetplanet;
     145
     146        if ( isset( $assoc['log-level'] ) )
     147            $planetplanet->set_loglevel( $assoc['log-level'] );
    147148
    148149        $planetplanet->purge_posts();
    149         WP_CLI::success( 'done.' );
     150        WP_CLI::success( __('Done.', 'planetplanet') );
    150151    }
    151152
     
    172173     *
    173174     */
    174     function scan($args, $assoc) {
     175    function scan( $args, $assoc ) {
    175176        global $planetplanet;
    176177
    177178        $site = $args[0];
    178179
    179         $response = $planetplanet->get_web_page($site);
    180         if (is_wp_error($response))
    181             WP_CLI::error($response);
     180        $response = $planetplanet->get_web_page( $site );
     181        if ( is_wp_error( $response ) )
     182            WP_CLI::error( $response );
    182183
    183184        $feed_links = [];
    184185
    185         $input = mb_convert_encoding($response['body'], 'HTML-ENTITIES', 'UTF-8');
    186         $xml = new DOMDocument('1.0', 'UTF-8');
    187         $error_mode = libxml_use_internal_errors(true);
    188 
    189         if ($xml->LoadHTML($input, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD)) {
    190             $links = $xml->getElementsByTagName('link');
    191 
    192             foreach ($links as $link) {
     186        $input = mb_convert_encoding( $response['body'], 'HTML-ENTITIES', 'UTF-8' );
     187        $xml = new DOMDocument( '1.0', 'UTF-8' );
     188        $error_mode = libxml_use_internal_errors( true );
     189
     190        if ($xml->LoadHTML( $input, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD )) {
     191            $links = $xml->getElementsByTagName( 'link' );
     192
     193            foreach ( $links as $link ) {
    193194                $attrs = $link->attributes;
    194195
    195196                // printf("LINK %s\n", $link->ownerDocument->saveXML($link));
    196197
    197                 $attr = $attrs->getNamedItem('rel');
    198                 if (!isset($attr) or $attr->value != 'alternate') continue;
    199 
    200                 $attr = $attrs->getNamedItem('type');
    201                 if (!isset($attr) or $attr->value != 'application/rss+xml') continue;
    202 
    203                 $attr = $attrs->getNamedItem('href');
    204                 if (!isset($attr) or empty($attr->value)) continue;
     198                $attr = $attrs->getNamedItem( 'rel' );
     199                if ( !isset( $attr ) or $attr->value != 'alternate' ) continue;
     200
     201                $attr = $attrs->getNamedItem( 'type' );
     202                if ( !isset( $attr ) or $attr->value != 'application/rss+xml' ) continue;
     203
     204                $attr = $attrs->getNamedItem( 'href' );
     205                if ( !isset( $attr ) or empty( $attr->value ) ) continue;
    205206                $href = $attr->value;
    206207
    207                 $attr = $attrs->getNamedItem('title');
    208                 if (!isset($attr) or empty($attr->value)) continue;
     208                $attr = $attrs->getNamedItem( 'title' );
     209                if ( !isset( $attr ) or empty( $attr->value ) ) continue;
    209210                $title = $attr->value;
    210211
    211                 $feed_links[] = [ 'Title' => $title, 'Feed url' => $href ];
     212                $feed_links[] = [ __('Title', 'planetplanet') => $title, __('Feed url', 'planetplanet') => $href ];
    212213            }
    213214        }
    214         libxml_use_internal_errors($error_mode);
    215 
    216         if ($feed_links) {
    217             WP_CLI\Utils\format_items( $assoc['format'], $feed_links, 'Title,Feed url' );
    218             $nfeeds = count($feed_links);
    219             WP_CLI::success("Found {$nfeeds} feeds.");
     215        libxml_use_internal_errors( $error_mode );
     216
     217        if ( $feed_links ) {
     218            WP_CLI\Utils\format_items( $assoc['format'], $feed_links, join(',', array_keys($feed_links[0])) );
     219            WP_CLI::success( sprintf( __('Found %d feeds.', 'planetplanet'), count( $feed_links )) );
     220        } else {
     221            WP_CLI::warning(__('No feeds found.', 'planetplanet'));
    220222        }
    221223    }
     
    231233     */
    232234
    233     function add($args, $assoc) {
     235    function add( $args, $assoc ) {
    234236        global $planetplanet;
    235237
    236238        $url = $args[0];
    237239
    238         if ($planetplanet->find_feed($url))
    239             WP_CLI::error("Feed already configured: $url");
    240 
    241         $response = $planetplanet->get_web_page($url);
    242         if (is_wp_error($response))
    243             WP_CLI::error($response);
    244 
    245         $data = $planetplanet->parse_feed($response['body']);
    246         if (is_wp_error($data))
    247             WP_CLI::error($data);
    248 
    249         if (isset($data['link_rss']) and $data['link_rss'] != $url) {
    250             if ($planetplanet->find_feed($data['link_rss']))
    251             WP_CLI::error("Feed already configured: {$data['link_rss']}");
     240        if ( $planetplanet->find_feed( $url ) )
     241            WP_CLI::error( sprintf( __("Feed already configured: %s", 'planetplanet'), $url ) );
     242
     243        $response = $planetplanet->get_web_page( $url );
     244        if ( is_wp_error( $response ) )
     245            WP_CLI::error( $response );
     246
     247        $data = $planetplanet->parse_feed( $response['body'] );
     248        if ( is_wp_error( $data ) )
     249            WP_CLI::error( $data );
     250
     251        if ( isset( $data['link_rss'] ) and $data['link_rss'] != $url ) {
     252            if ( $planetplanet->find_feed( $data['link_rss'] ) )
     253                WP_CLI::error( sprintf( __("Feed already configured: %s", 'planetplanet'), $data['link_rss'] ) );
    252254        }
    253255
     
    255257            'link_id' => 0,
    256258            'link_url' => $data['link'],
    257             'link_rss' => (!empty($data['link_rss']) ? $data['link_rss'] : $url),
     259            'link_rss' => ( !empty( $data['link_rss'] ) ? $data['link_rss'] : $url ),
    258260            'link_name' => $data['title'],
    259261        ];
    260262
    261         WP_CLI::log("Site name: {$link['link_name']}");
    262         WP_CLI::log("Site url: {$link['link_url']}");
    263         WP_CLI::log("Feed url: {$link['link_rss']}");
     263        WP_CLI::log( sprintf( __("Site name: %s", 'planetplanet'), $link['link_name'] ) );
     264        WP_CLI::log( sprintf( __("Site url: %s",  'planetplanet'), $link['link_url'] ) );
     265        WP_CLI::log( sprintf( __("Feed url: %s", 'planetplanet' ), $link['link_rss'] ) );
    264266
    265267        return;
    266268
    267         $id = wp_insert_link($link, true);
    268         if (is_wp_error($id))
    269             WP_CLI::error($id);
    270 
    271         WP_CLI::success("Link added");
     269        $id = wp_insert_link( $link, true );
     270        if ( is_wp_error( $id ) )
     271            WP_CLI::error( $id );
     272
     273        WP_CLI::success( __("Link added", 'planetplanet' ) );
    272274    }
    273275}
  • planetplanet/trunk/planetplanet.php

    r2650916 r2651566  
    1313 */
    1414
    15 require_once(ABSPATH . 'wp-admin/includes/taxonomy.php');
    16 require_once(ABSPATH . 'wp-admin/includes/bookmark.php');
     15require_once( ABSPATH . 'wp-admin/includes/taxonomy.php' );
     16require_once( ABSPATH . 'wp-admin/includes/bookmark.php' );
    1717// for media upload metadata
    18 require_once(ABSPATH . 'wp-admin/includes/image.php');
    19 require_once(ABSPATH . 'wp-admin/includes/media.php');
    20 
    21 require_once(__DIR__ . '/logger.php');
     18require_once( ABSPATH . 'wp-admin/includes/image.php' );
     19require_once( ABSPATH . 'wp-admin/includes/media.php' );
     20
     21require_once( __DIR__ . '/logger.php' );
    2222
    2323class PlanetPlanetPlugin {
     
    2626
    2727    function __construct() {
    28         $this->is_cli = (PHP_SAPI == 'cli');
     28        $this->is_cli = ( PHP_SAPI == 'cli' );
    2929
    3030        $this->set_loglevel();
    3131
    3232        // Activate the Links section in WP
    33         add_filter('pre_option_link_manager_enabled', '__return_true');
     33        add_filter( 'pre_option_link_manager_enabled', '__return_true' );
    3434
    3535        // Automatick setup of ajax handlers, actions, filters and shortcodes
    3636        // based on available class methods
    37         $methods = get_class_methods($this);
    38         foreach ($methods as $m) {
    39             if (preg_match('/^ajax_(.*)_handler$/', $m, $match)) {
    40                 add_action("wp_ajax_{$match[1]}", [$this, "ajax_{$match[1]}_handler"]);
    41             }
    42             elseif (preg_match('/^do_(.*)_shortcode$/', $m, $match)) {
    43                 add_shortcode($match[1], [$this, "do_{$match[1]}_shortcode"]);
    44             }
    45             elseif (preg_match('/^do_(.*)_action$/', $m, $match)) {
    46                 add_action($match[1], [$this, "do_{$match[1]}_action"]);
    47             }
    48             elseif (preg_match('/^do_(.*)_filter$/', $m, $match)) {
    49                 add_filter($match[1], [$this, "do_{$match[1]}_filter"]);
     37        $methods = get_class_methods( $this );
     38        foreach ( $methods as $m ) {
     39            if ( preg_match( '/^ajax_(.*)_handler$/', $m, $match ) ) {
     40                add_action( "wp_ajax_{$match[1]}", [ $this, "ajax_{$match[1]}_handler" ] );
     41            }
     42            elseif ( preg_match( '/^do_(.*)_shortcode$/', $m, $match ) ) {
     43                add_shortcode( $match[1], [ $this, "do_{$match[1]}_shortcode" ] );
     44            }
     45            elseif ( preg_match( '/^do_(.*)_action$/', $m, $match ) ) {
     46                add_action( $match[1], [ $this, "do_{$match[1]}_action" ] );
     47            }
     48            elseif ( preg_match( '/^do_(.*)_filter$/', $m, $match ) ) {
     49                add_filter( $match[1], [ $this, "do_{$match[1]}_filter" ] );
    5050            }
    5151        }
    5252    }
    5353
    54     public function set_loglevel($level = NULL) {
     54    public function set_loglevel( $level = NULL ) {
    5555        $this->logger = new \PlanetPlanet\PolyLogger();
    5656
    57         $loglevel = $level ?? $this->get_option('loglevel');
    58 
    59         $debug = ($loglevel == 'debug');
    60         $silent = ($loglevel == 'errors');
     57        $loglevel = $level ?? $this->get_option( 'loglevel' );
     58
     59        $debug = ( $loglevel == 'debug' );
     60        $silent = ( $loglevel == 'errors' );
    6161
    6262        $upload = wp_get_upload_dir();
    63         $logfile = sprintf('%s/%s-%s.log', $upload['basedir'], __CLASS__, date('Y-m-d'));
    64         if (!$this->is_cli or is_writable($logfile))
    65             $this->logger->add(new \PlanetPlanet\FileLogger($logfile, true));
    66 
    67         if ($this->is_cli)
    68             $this->logger->add(new \PlanetPlanet\CLILogger($debug, $silent));
    69         elseif ($this->has_option('email'))
    70             $this->logger->add(new \PlanetPlanet\MailLogger($this->get_option('email'), __CLASS__, $debug, $silent));
     63        $logfile = sprintf( '%s/%s-%s.log', $upload['basedir'], __CLASS__, date( 'Y-m-d' ) );
     64        if ( !$this->is_cli or is_writable( $logfile ) )
     65            $this->logger->add( new \PlanetPlanet\FileLogger( $logfile, true ) );
     66
     67        if ( $this->is_cli )
     68            $this->logger->add( new \PlanetPlanet\CLILogger( $debug, $silent ) );
     69        elseif ( $this->has_option( 'email' ) )
     70            $this->logger->add( new \PlanetPlanet\MailLogger( $this->get_option( 'email' ), __CLASS__, $debug, $silent ) );
    7171    }
    7272
     
    7878     ************************************************************************/
    7979
    80     function safe_datetime($time) {
     80    function safe_datetime( $time ) {
    8181        try {
    82             return new DateTime($time);
    83         } catch (Exception $e) {
     82            return new DateTime( $time );
     83        } catch ( Exception $e ) {
    8484            return NULL;
    8585        }
     
    8989    // - return response or WP_Error
    9090
    91     function get_web_page($url) {
     91    function get_web_page( $url ) {
    9292        $args = [
    9393            'sslverify' => false,
    9494        ];
    9595
    96         if ($this->has_option('timeout'))
    97             $args['timeout'] = $this->get_option('timeout');
    98 
    99         if ($this->has_option('user_agent'))
    100             $args['user-agent'] = $this->get_option('user_agent');
    101 
    102         $response = (new WP_Http())->get($url, $args);
    103 
    104         if (is_wp_error($response))
     96        if ( $this->has_option( 'timeout' ) )
     97            $args['timeout'] = $this->get_option( 'timeout' );
     98
     99        if ( $this->has_option( 'user_agent' ) )
     100            $args['user-agent'] = $this->get_option( 'user_agent' );
     101
     102        $response = ( new WP_Http() )->get( $url, $args );
     103
     104        if ( is_wp_error( $response ) )
    105105            return $response;
    106106
    107         if ($response['response']['code'] != WP_Http::OK)
    108             return new WP_Error('http_error',
    109                                 sprintf('HTTP response %d %s', $response['response']['code'], $response['response']['message']));
     107        if ( $response['response']['code'] != WP_Http::OK )
     108            return new WP_Error( 'http_error',
     109                                 sprintf( __('HTTP response %d %s', 'planetplanet'),
     110                                          $response['response']['code'],
     111                                          $response['response']['message']
     112                                 )
     113            );
    110114
    111115        return $response;
     
    118122     ************************************************************************/
    119123
    120     function get_option($name) {
    121         $options = get_option('planetplanet_options');
    122         if (array_key_exists($name, $options)) return $options[$name];
    123         if (array_key_exists("planetplanet_$name", $options)) return $options["planetplanet_$name"];
     124    function get_option( $name ) {
     125        $options = get_option( 'planetplanet_options' );
     126        if ( array_key_exists( $name, $options ) ) return $options[$name];
     127        if ( array_key_exists( "planetplanet_$name", $options ) ) return $options["planetplanet_$name"];
    124128        return NULL;
    125129    }
    126     function has_option($name) {
    127         return !empty($this->get_option($name));
     130    function has_option( $name ) {
     131        return !empty( $this->get_option( $name ) );
    128132    }
    129133
     
    144148            'manage_options',
    145149            'planetplanet',
    146             [$this, 'planetplanet_options_page_html']
     150            [ $this, 'planetplanet_options_page_html' ]
    147151        );
    148152    }
     
    158162        // wordpress will add the "settings-updated" $_GET parameter to the url
    159163        if ( isset( $_GET['settings-updated'] ) ) {
    160             add_settings_error('planetplanet', 'settings_saved', __( 'Settings Saved', 'planetplanet' ), 'updated');
     164            add_settings_error( 'planetplanet', 'settings_saved', __( 'Settings Saved', 'planetplanet' ), 'updated' );
    161165        }
    162166
     
    164168        // settings_errors('planetplanet');
    165169
    166         print('<div class="wrap">');
    167         printf('<h1>%s</h1>', esc_html(get_admin_page_title()));
    168         print('<form action="options.php" method="post">');
    169 
    170         settings_fields('planetplanet');
    171         do_settings_sections('planetplanet');
     170        print( '<div class="wrap">' );
     171        printf( '<h1>%s</h1>', esc_html( get_admin_page_title()  ) );
     172        print( '<form action="options.php" method="post">' );
     173
     174        settings_fields( 'planetplanet' );
     175        do_settings_sections( 'planetplanet' );
    172176        submit_button( 'Save Settings' );
    173177
    174         print('</form>');
    175         print('</div>');
     178        print( '</form>' );
     179        print( '</div>' );
    176180    }
    177181
     
    181185    function do_admin_init_action() {
    182186        // register a new setting for "planetplanet" page
    183         register_setting('planetplanet', 'planetplanet_options',
    184                          [ 'sanitize_callback' => [ $this, 'planetplanet_options_validate' ]],
    185                          [
    186                              'planetplanet_schedule' => 'hourly',
    187                              'planetplanet_retain_limit' => '1 year ago',
    188                              'planetplanet_email' => '',
    189                              'planetplanet_loglevel' => 'errors',
    190                          ],
     187        register_setting(
     188            'planetplanet', 'planetplanet_options',
     189            [ 'sanitize_callback' => [ $this, 'planetplanet_options_validate' ]],
     190            [
     191                'planetplanet_schedule' => 'hourly',
     192                'planetplanet_retain_limit' => '1 year ago',
     193                'planetplanet_email' => '',
     194                'planetplanet_loglevel' => 'errors',
     195            ],
    191196        );
    192197
     
    195200            'planetplanet_schedule_section',
    196201            __( 'Update schedule and retention', 'planetplanet' ),
    197             [$this, 'planetplanet_settings_html'],
     202            [ $this, 'planetplanet_settings_html' ],
    198203            'planetplanet'
    199204        );
    200205
    201206        $schedule_menu = [ 'none' => __('None', 'planetplanet') ];
    202         foreach (wp_get_schedules() as $k => $v)
     207        foreach ( wp_get_schedules() as $k => $v )
    203208            $schedule_menu[$k] = $v['display'];
    204209
     
    229234                'label_for' => 'planetplanet_retain_limit',
    230235                'settings' => 'planetplanet_options',
    231                 'help' => 'e.g., "1 year ago", "-6 months", "72 days ago"',
     236                'help' => __('e.g., "1 year ago", "-6 months", "72 days ago"', 'planetplanet'),
    232237            ]
    233238        );
     
    257262                ],
    258263
    259                 'help' => 'Feeds can always be reactivated in the Links manager',
     264                'help' => __('Feeds can always be reactivated in the Links manager', 'planetplanet'),
    260265            ]
    261266        );
     
    280285
    281286                'validator' => 'is_email',
    282                 'error' => 'Invalid email address will be ignored',
     287                'error' => __('Invalid email address will be ignored', 'planetplanet'),
    283288            ]
    284289        );
     
    297302                'default' => 'errors',
    298303                'menu' => [
    299                     'errors' => 'Only error messages',
    300                     'messages' => 'Errors and updates',
    301                     'debug' => 'Everything',
     304                    'errors' => __('Only error messages', 'planetplanet'),
     305                    'messages' => __('Errors and updates', 'planetplanet'),
     306                    'debug' => __('Everything', 'planetplanet'),
    302307                ],
    303308            ]
     
    311316            'planetplanet_network_section',
    312317            __( 'Network', 'planetplanet' ),
    313             [$this, 'planetplanet_settings_html'],
     318            [ $this, 'planetplanet_settings_html' ],
    314319            'planetplanet'
    315320        );
     
    318323            'timeout',
    319324            __( 'Timeout for feed requests', 'planetplanet' ),
    320             [$this, 'planetplanet_options_simple_menu_html'],
     325            [ $this, 'planetplanet_options_simple_menu_html' ],
    321326            'planetplanet',
    322327            'planetplanet_network_section',
     
    339344            'user_agent',
    340345            __( 'User-Agent', 'planetplanet' ),
    341             [$this, 'planetplanet_options_simple_input_html'],
     346            [ $this, 'planetplanet_options_simple_input_html' ],
    342347            'planetplanet',
    343348            'planetplanet_network_section',
     
    348353            ]
    349354        );
    350 
    351 
    352355    }
    353356
     
    357360     */
    358361
    359     function planetplanet_options_validate($input = NULl) {
    360         if (!empty($input['planetplanet_email']) and !is_email($input['planetplanet_email']))
    361             add_settings_error('planetplanet', 'invalid_email', __('Invalid email address for updates', 'planetplanet'));
    362 
    363         if (isset($input['planetplanet_retain_limit'])) {
    364             if (!$this->safe_datetime($input['planetplanet_retain_limit'])) {
    365                 add_settings_error('planetplanet', 'invalid_date', __('Invalid date value for discard limit', 'planetplanet'));
     362    function planetplanet_options_validate( $input = NULl ) {
     363        if ( !empty( $input['planetplanet_email'] ) and !is_email( $input['planetplanet_email'] ) )
     364            add_settings_error( 'planetplanet', 'invalid_email', __( 'Invalid email address for updates', 'planetplanet' ) );
     365
     366        if ( isset( $input['planetplanet_retain_limit'] ) ) {
     367            if ( !$this->safe_datetime( $input['planetplanet_retain_limit'] ) ) {
     368                add_settings_error( 'planetplanet', 'invalid_date', __( 'Invalid date value for discard limit', 'planetplanet' ) );
    366369                $input['planetplanet_retain_limit'] = NULL;
    367370            }
     
    371374    }
    372375
    373     function planetplanet_settings_html($args) {
    374     }
    375 
    376     function planetplanet_options_simple_menu_html($args) {
    377         $value = $this->get_option($args['field']) ?? $args['default'];
    378 
    379         printf('<select id="%s" name="%s[%s]">',
    380                esc_attr($args['field']),
    381                esc_attr($args['settings']),
    382                esc_attr($args['field']),
    383         );
    384         foreach ($args['menu'] as $k => $v)
    385             printf('<option value="%s" %s>%s</option>',
    386                    esc_attr($k),
    387                    ($value == $k ? 'selected' : ''),
    388                    esc_html($v)
     376    function planetplanet_settings_html( $args ) {
     377    }
     378
     379    function planetplanet_options_simple_menu_html( $args ) {
     380        $value = $this->get_option( $args['field'] ) ?? $args['default'];
     381
     382        printf( '<select id="%s" name="%s[%s]">',
     383                esc_attr( $args['field'] ),
     384                esc_attr( $args['settings'] ),
     385                esc_attr( $args['field'] ),
     386        );
     387        foreach ( $args['menu'] as $k => $v )
     388            printf( '<option value="%s" %s>%s</option>',
     389                    esc_attr( $k ),
     390                    ( $value == $k ? 'selected' : '' ),
     391                    esc_html( $v )
    389392            );
    390         printf('</select>');
    391 
    392         if (isset($args['help'])) {
    393             printf('<p>%s</p>', $args['help']);
    394         }
    395     }
    396 
    397     function planetplanet_options_simple_input_html($args) {
    398         $options = get_option('planetplanet_options');
    399         $value = isset($options[$args['field']]) ? $options[$args['field']] : '';
    400         printf('<input type="text" id="%s" name="%s[%s]" value="%s">',
    401                esc_attr($args['field']),
    402                esc_attr($args['settings']),
    403                esc_attr($args['field']),
    404                esc_attr($value)
    405         );
    406 
    407         if (isset($args['validator']) and is_callable($args['validator']) and !empty($value) and !empty($args['error'])) {
    408             $valid = call_user_func($args['validator'], $value);
    409             if (!$valid)
    410                 printf('<div style="color:red">%s</div>', $args['error']);
    411         }
    412         if (isset($args['help'])) {
    413             printf('<div>%s</div>', $args['help']);
     393        printf( '</select>' );
     394
     395        if ( isset( $args['help'] ) ) {
     396            printf( '<p>%s</p>', $args['help'] );
     397        }
     398    }
     399
     400    function planetplanet_options_simple_input_html( $args ) {
     401        $options = get_option( 'planetplanet_options' );
     402        $value = isset( $options[$args['field']] ) ? $options[$args['field']] : '';
     403        printf( '<input type="text" id="%s" name="%s[%s]" value="%s">',
     404               esc_attr( $args['field'] ),
     405               esc_attr( $args['settings'] ),
     406               esc_attr( $args['field'] ),
     407               esc_attr( $value )
     408         );
     409
     410        if ( isset( $args['validator'] ) and is_callable( $args['validator'] ) and !empty( $value ) and !empty( $args['error'] ) ) {
     411            $valid = call_user_func( $args['validator'], $value );
     412            if ( !$valid )
     413                printf( '<div style="color:red">%s</div>', $args['error'] );
     414        }
     415        if ( isset( $args['help'] ) ) {
     416            printf( '<div>%s</div>', $args['help'] );
    414417        }
    415418    }
     
    423426     ************************************************************************/
    424427
    425     function redirect($url) {
    426         wp_redirect($url);
     428    function redirect( $url ) {
     429        wp_redirect( $url );
    427430        die;
    428431    }
     
    432435        global $post;
    433436
    434         if (!$post) return;
    435 
    436         if (is_single()) {
    437             if ($target = $post->item_link) {
     437        if ( !$post ) return;
     438
     439        if ( is_single() ) {
     440            if ( $target = $post->item_link ) {
    438441                # If it looks like an URL go there
    439                 if (strpos($target, 'https://') === 0 || strpos($target, 'http://') === 0) {
    440                     $this->redirect($target);
     442                if ( strpos( $target, 'https://' ) === 0 || strpos( $target, 'http://' ) === 0 ) {
     443                    $this->redirect( $target );
    441444                }
    442445            }
    443446        }
    444         elseif (is_category()) {
     447        elseif ( is_category() ) {
    445448            $cat = get_queried_object();
    446             $target = $this->get_category_link($cat);
    447             if ($target)
    448                 $this->redirect($target);
     449            $target = $this->get_category_link( $cat );
     450            if ( $target )
     451                $this->redirect( $target );
    449452        }
    450453    }
     
    465468
    466469    function do_init_action() {
    467         register_deactivation_hook( __FILE__, function () {
    468             wp_clear_scheduled_hook('pp_update_feeds');
    469             wp_clear_scheduled_hook('pp_purge_posts');
    470         });
    471 
    472         $schedule = $this->get_option('schedule');
    473         if (isset($schedule) and $schedule == 'none')
     470        register_deactivation_hook(  __FILE__, function () {
     471            wp_clear_scheduled_hook( 'pp_update_feeds' );
     472            wp_clear_scheduled_hook( 'pp_purge_posts' );
     473        } );
     474
     475        $schedule = $this->get_option( 'schedule' );
     476        if ( isset( $schedule ) and $schedule == 'none' )
    474477            $schedule = NULL;
    475478
    476         if ($schedule) {
     479        if ( $schedule ) {
    477480            $schedules = wp_get_schedules();
    478             if (!isset($schedules[$schedule]))
     481            if ( !isset( $schedules[$schedule] ) )
    479482                $schedule = NULL;
    480483        }
    481484
    482485        // Next scheduled event
    483         $event = wp_get_scheduled_event('pp_update_feeds');
    484 
    485         if ($schedule) {
    486             if ($event === false) {
     486        $event = wp_get_scheduled_event( 'pp_update_feeds' );
     487
     488        if ( $schedule ) {
     489            if ( $event === false ) {
    487490                // Not scheduled but should be
    488                 wp_schedule_event(time(), $schedule, 'pp_update_feeds');
    489             }
    490             elseif ($event->schedule != $schedule) {
     491                wp_schedule_event( time(), $schedule, 'pp_update_feeds' );
     492            }
     493            elseif ( $event->schedule != $schedule ) {
    491494                // Scheduled but not correctly
    492                 wp_clear_scheduled_hook('pp_update_feeds');
     495                wp_clear_scheduled_hook( 'pp_update_feeds' );
    493496
    494497                $when = $event->timestamp;
    495                 if ($when > time() + $schedules[$schedule]['interval'])
     498                if ( $when > time() + $schedules[$schedule]['interval'] )
    496499                    $when = time() + $schedules[$schedule]['interval'];
    497500
    498                 wp_schedule_event($when, $schedule, 'pp_update_feeds');
     501                wp_schedule_event( $when, $schedule, 'pp_update_feeds' );
    499502            }
    500503        } else {
    501504            // Shouldn't be scheduled
    502             if ($event)
    503                 wp_clear_scheduled_hook('pp_update_feeds');
     505            if ( $event )
     506                wp_clear_scheduled_hook( 'pp_update_feeds' );
    504507        }
    505508
    506509        // Do the purge handler too
    507         if (! wp_next_scheduled('pp_purge_posts')) {
    508             wp_schedule_event(time() + WEEK_IN_SECONDS, 'weekly', 'pp_purge_posts');
     510        if ( !wp_next_scheduled( 'pp_purge_posts' ) ) {
     511            wp_schedule_event( time() + WEEK_IN_SECONDS, 'weekly', 'pp_purge_posts' );
    509512        }
    510513    }
     
    518521     ************************************************************************/
    519522
    520     function parse_feed($feed) {
    521         $error_mode = libxml_use_internal_errors(true);
     523    function parse_feed( $feed ) {
     524        $error_mode = libxml_use_internal_errors( true );
    522525        try {
    523             $xml = new SimpleXMLElement($feed);
    524         } catch (Exception $e) {
     526            $xml = new SimpleXMLElement( $feed );
     527        } catch ( Exception $e ) {
    525528            $xml = NULL;
    526529        }
    527         libxml_use_internal_errors($error_mode);
    528 
    529         if (empty($xml)) {
    530             return new WP_Error('xml_parse_error', "Feed is not XML");
     530        libxml_use_internal_errors( $error_mode );
     531
     532        if ( empty( $xml ) ) {
     533            return new WP_Error( 'xml_parse_error', "Feed is not XML" );
    531534        }
    532535
    533536        $ns = $xml->GetDocNamespaces();
    534537
    535         if ($xml->getName() == "rss") {
     538        if ( $xml->getName() == "rss" ) {
    536539            $output = [
    537540                'title' => (string)$xml->channel->title,
     
    540543            ];
    541544
    542             if (empty($output['title']))
     545            if ( empty( $output['title'] ) )
    543546                $output['title'] = $output['link'];
    544547
    545             if (isset($ns['atom']))
    546                 $feed_url = $xml->channel->children($ns['atom'])->link;
    547 
    548             if (isset($feed_url) and count($feed_url)>0)
    549                 if ((string)$feed_url->attributes()->type == 'application/rss+xml')
     548            if ( isset( $ns['atom'] ) )
     549                $feed_url = $xml->channel->children( $ns['atom'] )->link;
     550
     551            if ( isset( $feed_url ) and count( $feed_url ) > 0 )
     552                if ( (string)$feed_url->attributes()->type == 'application/rss+xml' )
    550553                    $output['link_rss'] = (string)$feed_url->attributes()->href;
    551554
    552555            $output['posts'] = [];
    553             foreach ($xml->channel->item as $item) {
    554                 if (isset($ns['dc']))
    555                     $author = (string)$item->children($ns['dc'])->creator;
    556                 if (empty($author))
     556            foreach ( $xml->channel->item as $item ) {
     557                if ( isset( $ns['dc'] ) )
     558                    $author = (string)$item->children( $ns['dc'] )->creator;
     559                if ( empty( $author ) )
    557560                    $author = (string)$item->author;
    558561
    559                 $post_date = DateTime::createFromFormat(DateTime::RSS, (string)$item->pubDate);
    560                 if (!$post_date) {
     562                $post_date = DateTime::createFromFormat( DateTime::RSS, (string)$item->pubDate );
     563                if ( !$post_date ) {
    561564                    continue;
    562565                }
    563566
    564                 if (isset($ns['content']))
    565                     $post_content = (string)$item->children($ns['content'])->encoded;
     567                if ( isset($ns['content']) )
     568                    $post_content = (string)$item->children( $ns['content'] )->encoded;
    566569
    567570                $post = [
    568571                    'post_title' => (string)$item->title,
    569                     'post_date' => $post_date->format('Y-m-d H:i:s'),
    570 
    571                     'post_excerpt' => strip_tags((string)$item->description),
     572                    'post_date' => $post_date->format( 'Y-m-d H:i:s' ),
     573
     574                    'post_excerpt' => strip_tags( (string)$item->description ),
    572575                    'post_content' => $post_content ?? '',
    573576
    574                     'guid' => site_url((string)$item->guid, 'https'),
     577                    'guid' => site_url( (string)$item->guid, 'https' ),
    575578
    576579                    'meta_input' => [
     
    584587            }
    585588        }
    586         elseif ($xml->getName() == "feed") {
     589        elseif ( $xml->getName() == "feed" ) {
    587590            $output = [
    588591                'title' => (string)$xml->title,
     
    590593            ];
    591594
    592             foreach ($xml->link as $link) {
    593                 if ($link->attributes()->rel == "alternate" and $link->attributes()->type == "text/html") {
     595            foreach ( $xml->link as $link ) {
     596                if ( $link->attributes()->rel == "alternate" and $link->attributes()->type == "text/html" ) {
    594597                    $output['link'] = (string)$link->attributes()->href;
    595598                    break;
     
    597600            }
    598601
    599             if (empty($output['title']))
     602            if ( empty( $output['title'] ) )
    600603                $output['title'] = $output['link'];
    601604
    602605            $output['posts'] = [];
    603             foreach ($xml->entry as $item) {
     606            foreach ( $xml->entry as $item ) {
    604607                $item_link = NULL;
    605                 foreach ($item->link as $link) {
    606                     if ($link->attributes()->rel == "alternate" and $link->attributes()->type == "text/html") {
     608                foreach ( $item->link as $link ) {
     609                    if ( $link->attributes()->rel == "alternate" and $link->attributes()->type == "text/html" ) {
    607610                        $item_link = (string)$link->attributes()->href;
    608611                        break;
    609612                    }
    610613                }
    611                 $post_date = DateTime::createFromFormat(DateTime::RFC3339, (string)$item->published);
    612                 if (!$post_date)
    613                     $post_date = DateTime::createFromFormat(DateTime::RFC3339_EXTENDED, (string)$item->published);
    614                 if (!$post_date)
     614                $post_date = DateTime::createFromFormat( DateTime::RFC3339, (string)$item->published );
     615                if ( !$post_date )
     616                    $post_date = DateTime::createFromFormat( DateTime::RFC3339_EXTENDED, (string)$item->published );
     617                if ( !$post_date )
    615618                    continue;   // Skip if we can't understand the date
    616619
    617620                $post = [
    618621                    'post_title' => (string)$item->title,
    619                     'post_date' => $post_date->format('Y-m-d H:i:s'),
     622                    'post_date' => $post_date->format( 'Y-m-d H:i:s' ),
    620623
    621624                    'post_excerpt' => (string)$item->summary,
    622625                    'post_content' => (string)$item->content,
    623626
    624                     'guid' => site_url((string)$item->id, 'https'),
     627                    'guid' => site_url( (string)$item->id, 'https' ),
    625628
    626629                    'meta_input' => [
     
    631634                ];
    632635
    633                 // print_r($post);
     636                // print_r( $post );
    634637
    635638                $output['posts'][] = $post;
     
    640643        }
    641644
    642         foreach ($output['posts'] as &$post) {
     645        foreach ( $output['posts'] as &$post ) {
    643646            $post['ID'] = 0;
    644647            $post['post_status'] = 'publish';
    645648
    646             if (empty(trim($post['post_title'])))
     649            if ( empty( trim( $post['post_title'] ) ) )
    647650                $post['post_title'] = 'No title';
    648651
     
    661664     ************************************************************************/
    662665
    663     function find_feed($url) {
     666    function find_feed( $url ) {
    664667        $links = get_bookmarks();
    665         if ($links) {
    666             $url = htmlentities($url); // link_rss seems to be encoded
     668        if ( $links ) {
     669            $url = htmlentities( $url ); // link_rss seems to be encoded
    667670            foreach ($links as $link) {
    668                 // $this->logger->debug('Testing link «%s» ~ «%s»', $link->link_rss, $url);
    669                 if (!empty($link->link_rss) and $link->link_rss == $url)
     671                // $this->logger->debug( 'Testing link «%s» ~ «%s»', $link->link_rss, $url );
     672                if ( !empty( $link->link_rss ) and $link->link_rss == $url )
    670673                    return $link;
    671674            }
     
    680683     ************************************************************************/
    681684
    682     function generate_category_slug($url) {
    683         if (0 === stripos($url, 'http://'))
    684             $url = substr($url, 7);
    685         elseif (0 === stripos($url, 'https://'))
    686             $url = substr($url, 8);
    687 
    688         return sanitize_title($url);
    689     }
    690 
    691     function get_link_category($link) {
    692         $cat_slug = $this->generate_category_slug($link->link_url);
    693         $cat = get_term_by('slug', $cat_slug, 'category');
    694 
    695         if ($cat !== False)
     685    function generate_category_slug( $url ) {
     686        if ( 0 === stripos( $url, 'http://' ) )
     687            $url = substr( $url, 7 );
     688        elseif ( 0 === stripos( $url, 'https://' ) )
     689            $url = substr( $url, 8 );
     690
     691        return sanitize_title( $url );
     692    }
     693
     694    function get_link_category( $link ) {
     695        $cat_slug = $this->generate_category_slug( $link->link_url );
     696        $cat = get_term_by( 'slug', $cat_slug, 'category' );
     697
     698        if ( $cat !== False )
    696699            return $cat->term_id;
    697700
    698         $this->logger->debug("Creating category $cat_slug\n");
    699 
    700         $cat_id = wp_insert_category([
     701        $this->logger->debug( __( "Creating category %d", 'planetplanet' ), $cat_slug );
     702
     703        $cat_id = wp_insert_category( [
    701704            'cat_ID' => 0,
    702705            'cat_name' => $link->link_name,
    703706            'category_nicename' => $cat_slug,
    704             'category_description' => sprintf("<!-- %s -->\n", $link->link_url),
    705         ], true);
    706 
    707         if (is_wp_error($cat_id)) {
    708             $this->logger->error('Failed to create category %s: %s', $cat_slug, $cat_id->get_error_message());
     707            'category_description' => sprintf( "<!-- %s -->\n", $link->link_url ),
     708        ], true );
     709
     710        if ( is_wp_error( $cat_id ) ) {
     711            $this->logger->error( __( 'Failed to create category %s: %s', 'planetplanet' ),
     712                                  $cat_slug,
     713                                  $cat_id->get_error_message()
     714            );
    709715            return false;
    710716        }
     
    713719    }
    714720
    715     function get_category_link($cat) {
    716         $linkmap = get_transient('planetplanet_category_linkmap');
    717 
    718         if (isset($linkmap) and isset($linkmap[$cat->term_id]))
     721    function get_category_link( $cat ) {
     722        $linkmap = get_transient( 'planetplanet_category_linkmap' );
     723
     724        if ( isset( $linkmap ) and isset( $linkmap[$cat->term_id] ) )
    719725            return $linkmap[$cat->term_id];
    720726
    721727        $linkmap = [];
    722         foreach (get_bookmarks() as $link) {
    723             $slug = $this->generate_category_slug($link->link_url);
    724             $linkcat = get_term_by('slug', $slug, 'category');
    725 
    726             if ($linkcat)
     728        foreach ( get_bookmarks() as $link ) {
     729            $slug = $this->generate_category_slug( $link->link_url );
     730            $linkcat = get_term_by( 'slug', $slug, 'category' );
     731
     732            if ( $linkcat )
    727733                $linkmap[$linkcat->term_id] = $link->link_url;
    728734        }
    729         set_transient('planetplanet_category_linkmap', $linkmap);
    730 
    731         return isset($linkmap[$cat->term_id]) ? $linkmap[$cat->term_id] : NULL;
     735        set_transient( 'planetplanet_category_linkmap', $linkmap );
     736
     737        return isset( $linkmap[$cat->term_id] ) ? $linkmap[$cat->term_id] : NULL;
    732738    }
    733739
     
    738744     ************************************************************************/
    739745
    740     function import_feed_items($link) {
    741         $response = $this->get_web_page($link->link_rss);
    742         if (is_wp_error($response)) return $response;
    743 
    744         $data = $this->parse_feed($response['body']);
    745         if (is_wp_error($data)) return $data;
     746    function import_feed_items( $link ) {
     747        $response = $this->get_web_page( $link->link_rss );
     748        if ( is_wp_error( $response ) ) return $response;
     749
     750        $data = $this->parse_feed( $response['body'] );
     751        if ( is_wp_error( $data ) ) return $data;
    746752
    747753        // find feed category and create if necessary
    748         $cat_id = $this->get_link_category($link);
    749         $this->logger->debug("Feed category ID $cat_id\n");
     754        $cat_id = $this->get_link_category( $link );
     755        $this->logger->debug( __( "Feed category ID %d", 'planetplanet' ), $cat_id );
    750756
    751757        $posts = $data['posts'];
    752         if (empty($posts)) return false; // nothing to import
     758        if ( empty( $posts ) ) return false; // nothing to import
    753759
    754760        $limit = NULL;
    755         if ($this->has_option('retain_limit'))
    756             $limit = $this->safe_datetime($this->get_option('retain_limit'));
     761        if ($this->has_option( 'retain_limit' ))
     762            $limit = $this->safe_datetime( $this->get_option('retain_limit') );
    757763
    758764        $old = 0;
     
    761767        $mtime = NULL;
    762768
    763         foreach ($posts as $post) {
    764             $dt = new DateTime($post['post_date']);
    765 
    766             if (!$mtime or $dt > $mtime)
     769        foreach ( $posts as $post ) {
     770            $dt = new DateTime( $post['post_date'] );
     771
     772            if ( !$mtime or $dt > $mtime )
    767773                $mtime = $dt;
    768774
    769             if ($limit) {
     775            if ( $limit ) {
    770776                // Check post age - this if for recentish stuff
    771777                if ($dt < $limit) {
    772778                    $old = $old + 1;
    773                     $this->logger->debug("Old post %s - %s", $post['post_title'], $post['post_date']);
     779                    $this->logger->debug( __( "Old post %s - %s", 'planetplanet' ), $post['post_title'], $post['post_date'] );
    774780                    continue;
    775781                }
     
    777783
    778784            // Check that we don't already have the post
    779             $olds = get_posts([
     785            $olds = get_posts( [
    780786                'post_type' => 'post',
    781787                'meta_key' => 'item_link',
    782788                'meta_value' =>  $post['meta_input']['item_link'],
    783             ]);
    784             if (!empty($olds)) {
     789            ] );
     790            if ( !empty($olds) ) {
    785791                $seen = $seen + 1;
    786                 $this->logger->debug("Seen post %s - %s", $post['post_title'], $post['post_date']);
     792                $this->logger->debug( __( "Seen post %s - %s", 'planetplanet' ), $post['post_title'], $post['post_date'] );
    787793                continue;
    788794            }
    789795
    790796            $new = $new + 1;
    791             $this->logger->message("New post found for %s - %s", $link->link_name, $link->link_rss);
    792             $this->logger->message(" - new post %s - %s", $post['post_title'], $post['meta_input']['item_link']);
     797            $this->logger->message( __( "New post found for %s - %s", 'planetplanet' ), $link->link_name, $link->link_rss );
     798            $this->logger->message( __( " - new post %s - %s", 'planetplanet' ), $post['post_title'], $post['meta_input']['item_link'] );
    793799
    794800            // Add category for post
    795801            $post['post_category'] = [ $cat_id ];
    796             $post_id = wp_insert_post($post);
    797             if (is_wp_error($post_id)) return $post_id;
    798 
    799             $this->get_featured_image($post_id);
    800         }
    801 
    802         if ($new)
    803             $this->logger->message('Feed status %3d "%s" - %d new, %d seen, %d old',
    804                                    $link->link_id, $link->link_name,
    805                                    $new, $seen, $old
     802            $post_id = wp_insert_post( $post );
     803            if ( is_wp_error( $post_id ) ) return $post_id;
     804
     805            $this->get_featured_image( $post_id );
     806        }
     807
     808        if ( $new )
     809            $this->logger->message( __( 'Feed status %3d "%s" - %d new, %d seen, %d old', 'planetplanet' ),
     810                                    $link->link_id, $link->link_name,
     811                                    $new, $seen, $old
    806812            );
    807813
    808         return $mtime ? $mtime->format('Y-m-d H:i:s') : false;
     814        return $mtime ? $mtime->format( 'Y-m-d H:i:s' ) : false;
    809815    }
    810816
     
    812818    //
    813819
    814     function get_featured_image($post_id) {
    815         if (!$post_id) return;
    816 
    817         $post = get_post($post_id);
    818         if (!$post) return;
    819         if (!$post->item_link) return;
    820         if (has_post_thumbnail($post)) return;
    821 
    822         $response = $this->get_web_page($post->item_link);
    823         if (is_wp_error($response)) return;
    824 
    825         $html = mb_convert_encoding($response['body'], 'HTML-ENTITIES', 'UTF-8');
    826         $xml = new DOMDocument('1.0', 'UTF-8');
    827         $error_mode = libxml_use_internal_errors(true);
     820    function get_featured_image( $post_id ) {
     821        if ( !$post_id ) return;
     822
     823        $post = get_post( $post_id );
     824        if ( !$post ) return;
     825        if ( !$post->item_link ) return;
     826        if ( has_post_thumbnail( $post ) ) return;
     827
     828        $response = $this->get_web_page( $post->item_link );
     829        if ( is_wp_error( $response ) ) return;
     830
     831        $html = mb_convert_encoding( $response['body'], 'HTML-ENTITIES', 'UTF-8' );
     832        $xml = new DOMDocument( '1.0', 'UTF-8' );
     833        $error_mode = libxml_use_internal_errors( true );
    828834
    829835        $image_url = NULL;
    830         if ($xml->LoadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD)) {
    831             $elems = $xml->getElementsByTagName('meta');
    832 
    833             foreach ($elems as $elem) {
     836        if ( $xml->LoadHTML( $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ) ) {
     837            $elems = $xml->getElementsByTagName( 'meta' );
     838
     839            foreach ( $elems as $elem ) {
    834840                $attrs = $elem->attributes;
    835841
    836                 $attr = $attrs->getNamedItem('property');
    837                 if (isset($attr) and $attr->value == 'og:image') {
    838                     $attr = $attrs->getNamedItem('content');
    839                     if (isset($attr) and !empty($attr->value)) {
     842                $attr = $attrs->getNamedItem( 'property' );
     843                if ( isset( $attr ) and $attr->value == 'og:image' ) {
     844                    $attr = $attrs->getNamedItem( 'content' );
     845                    if ( isset( $attr ) and !empty( $attr->value ) ) {
    840846                        $image_url = $attr->value;
    841847                        break;
     
    844850            }
    845851        }
    846         libxml_use_internal_errors($error_mode);
    847 
    848         if (empty($image_url)) {
    849             $this->logger->message('No image found in %s', $post->item_link);
     852        libxml_use_internal_errors( $error_mode );
     853
     854        if ( empty( $image_url ) ) {
     855            $this->logger->message( __( 'No image found in %s', 'planetplanet' ), $post->item_link );
    850856            return;
    851857        };
    852858
    853         $image_url = WP_Http::make_absolute_url($image_url, $post->item_link);
    854 
    855         $this->logger->debug('Found image url %s', $image_url);
     859        $image_url = WP_Http::make_absolute_url( $image_url, $post->item_link );
     860
     861        $this->logger->debug( __( 'Found image url %s', 'planetplanet' ), $image_url );
    856862
    857863        // Check if we already has that image saved
    858         $images = get_posts([
     864        $images = get_posts( [
    859865            'post_type' => 'attachment',
    860866            'post_status' => 'inherit',
    861867            'meta_key' => 'source_url',
    862868            'meta_value' => $image_url,
    863         ]);
    864 
    865 
    866         if (empty($images)) {
     869        ] );
     870
     871
     872        if ( empty( $images ) ) {
    867873            // Download the image and upload it to the site
    868874
    869             $response = $this->get_web_page($image_url);
    870             if (is_wp_error($response)) {
    871                 $this->logger->error('Failed to retrieve %s: %s', $image_url, $response->get_error_message(0));
     875            $response = $this->get_web_page( $image_url );
     876            if ( is_wp_error( $response ) ) {
     877                $this->logger->error( __( 'Failed to retrieve %s: %s', 'planetplanet' ), $image_url, $response->get_error_message(0) );
    872878                return;
    873879            }
    874880
    875881            $bits = $response['body'];
    876             $filename = basename(parse_url($image_url, PHP_URL_PATH));
     882            $filename = basename( parse_url( $image_url, PHP_URL_PATH ) );
    877883
    878884            // If no filename extension, check http_response_headers
    879             if (empty(pathinfo($filename, PATHINFO_EXTENSION))) {
     885            if ( empty( pathinfo( $filename, PATHINFO_EXTENSION ) ) ) {
    880886                $content_disp = $response['headers']['Content-Disposition'];
    881887
    882                 if (preg_match('/\bfilename="(.*?)"/', $content_disp, $m)) {
    883                     $this->logger->debug('Using filename from HTTP response «%s»', $m[1]);
     888                if ( preg_match( '/\bfilename="(.*?)"/', $content_disp, $m ) ) {
     889                    $this->logger->debug( __( 'Using filename from HTTP response «%s»', 'planetplanet' ), $m[1] );
    884890                    $filename = $m[1];
    885891                }
    886                 elseif (preg_match('/\bfilename=(.*?)$/', $content_disp, $m)) {
    887                     $this->logger->debug('Using filename from HTTP response «%s»', $m[1]);
     892                elseif ( preg_match( '/\bfilename=(.*?)$/', $content_disp, $m ) ) {
     893                    $this->logger->debug( __( 'Using filename from HTTP response «%s»', 'planetplanet' ), $m[1] );
    888894                    $filename = $m[1];
    889895                }
    890896            }
    891897
    892             $upload_file = wp_upload_bits($filename, NULL, $bits);
    893 
    894             if ($upload_file['error']) {
    895                 $this->loggger->error('Image upload error %s', $upload_file['error']);
     898            $upload_file = wp_upload_bits( $filename, NULL, $bits );
     899
     900            if ( $upload_file['error'] ) {
     901                $this->loggger->error( __( 'Image upload error %s', 'planetplanet' ), $upload_file['error'] );
    896902                return;
    897903            }
    898904
    899             $filetype = wp_check_filetype($upload_file['file'], NULL);
     905            $filetype = wp_check_filetype( $upload_file['file'], NULL );
    900906
    901907            $attachment = [
    902908                'guid' => $upload_file['url'],
    903909                'post_mime_type' => $filetype['type'],
    904                 'post_title' => sanitize_file_name($filename),
     910                'post_title' => sanitize_file_name( $filename ),
    905911                'post_content' => '',
    906912                'post_status' => 'inherit',
     
    908914            ];
    909915
    910             $this->logger->debug('Registering attachment %s', $upload_file['file']);
    911 
    912             $attachment_id = wp_insert_attachment($attachment, $upload_file['file'], $post->ID, true);
    913             if (is_wp_error($attachment_id)) {
    914                 $this->logger->error('Image attachment error %s', $attachment_id->get_error_message());
     916            $this->logger->debug( __( 'Registering attachment %s', 'planetplanet' ), $upload_file['file'] );
     917
     918            $attachment_id = wp_insert_attachment( $attachment, $upload_file['file'], $post->ID, true );
     919            if ( is_wp_error( $attachment_id ) ) {
     920                $this->logger->error( __( 'Image attachment error %s', 'planetplanet' ), $attachment_id->get_error_message() );
    915921                return;
    916922            }
    917923
    918             $this->logger->debug('Created attachment id %d', $attachment_id);
    919 
    920             $attachment_data = wp_generate_attachment_metadata($attachment_id, $upload_file['file']);
    921             wp_update_attachment_metadata($attachment_id,  $attachment_data);
     924            $this->logger->debug( __( 'Created attachment id %d', 'planetplanet' ), $attachment_id );
     925
     926            $attachment_data = wp_generate_attachment_metadata( $attachment_id, $upload_file['file'] );
     927            wp_update_attachment_metadata( $attachment_id,  $attachment_data );
    922928
    923929            // Save the source of the image
    924             add_post_meta($attachment_id, 'source_url', $image_url);
     930            add_post_meta( $attachment_id, 'source_url', $image_url );
    925931        } else {
    926932            $attachment_id = $images[0]->ID;
    927             $this->logger->debug('Using existing attachment id %d', $attachment_id);
     933            $this->logger->debug( __( 'Using existing attachment id %d', 'planetplanet' ), $attachment_id );
    928934        }
    929935
    930936        // Attach image to post
    931         $success = set_post_thumbnail($post, $attachment_id);
    932         if (!$success) return;
    933 
    934         $this->logger->message('Downloaded post thumbnail');
     937        $success = set_post_thumbnail( $post, $attachment_id );
     938        if ( !$success ) return;
     939
     940        $this->logger->message( __( 'Downloaded post thumbnail', 'planetplanet' ) );
    935941        return $success;
    936942    }
     
    939945    // WP db links
    940946
    941     function update_feed($link) {
    942         $this->logger->debug('Starting import of %s - %s', $link->link_name, $link->link_url);
    943 
    944         $mtime = $this->import_feed_items($link);
    945 
    946         if (is_wp_error($mtime)) {
     947    function update_feed( $link ) {
     948        $this->logger->debug( __( 'Starting import of %s - %s', 'planetplanet' ), $link->link_name, $link->link_url );
     949
     950        $mtime = $this->import_feed_items( $link );
     951
     952        if ( is_wp_error( $mtime ) ) {
    947953            $msg = $mtime->get_error_message();
    948             $link->link_notes = substr($msg, 0, 255);
     954            $link->link_notes = substr( $msg, 0, 255 );
    949955            $link->link_rating = $link->link_rating + 1;
    950956
    951             $max_errors = $this->get_option('max_errors') ?? 5;
    952 
    953             $this->logger->error('Feed %d "%s" - Error #%d/%d: %s: %s',
    954                                  $link->link_id,
    955                                  $link->link_name,
    956                                  $link->link_rating,
    957                                  $max_errors,
    958                                  $link->link_rss,
    959                                  $msg
     957            $max_errors = $this->get_option( 'max_errors' ) ?? 5;
     958
     959            $this->logger->error( __( 'Feed %d "%s" - Error #%d/%d: %s: %s', 'planetplanet' ),
     960                                  $link->link_id,
     961                                  $link->link_name,
     962                                  $link->link_rating,
     963                                  $max_errors,
     964                                  $link->link_rss,
     965                                  $msg
    960966            );
    961967
    962             if ($link->link_rating >= $max_errors) {
    963                 $this->logger->error('Feed %d "%s" suspended: too many errors', $link->link_id, $link->link_name);
     968            if ( $link->link_rating >= $max_errors ) {
     969                $this->logger->error( __( 'Feed %d "%s" suspended: too many errors', 'planetplanet' ),
     970                                      $link->link_id, $link->link_name );
    964971                $link->link_visible = 'N';
    965972            }
     
    971978        }
    972979
    973         $this->logger->debug('Updating %d "%s" - mtime %s', $link->link_id, $link->link_name, $mtime);
    974         $link_id = wp_insert_link(get_object_vars($link), true);
    975         if (is_wp_error($link_id))
    976             $this->logger->error('Saving link %d failed: %s', $link->link_id, $link_id->get_error_message());
     980        $this->logger->debug( __( 'Updating %d "%s" - mtime %s', 'planetplanet' ),
     981                              $link->link_id, $link->link_name, $mtime );
     982        $link_id = wp_insert_link( get_object_vars( $link ), true );
     983        if ( is_wp_error( $link_id ) )
     984            $this->logger->error( __( 'Saving link %d failed: %s', 'planetplanet' ),
     985                                  $link->link_id, $link_id->get_error_message() );
    977986
    978987        // NOT NICE - wp_update_link() doesn't update the link_updated field
    979988
    980         if ($mtime) {
     989        if ( $mtime ) {
    981990            global $wpdb;
    982             $wpdb->update("{$wpdb->prefix}links",
    983                           [ 'link_updated' => $mtime ],
    984                           [ 'link_id' => $link->link_id ]
     991            $wpdb->update( "{$wpdb->prefix}links",
     992                           [ 'link_updated' => $mtime ],
     993                           [ 'link_id' => $link->link_id ]
    985994            );
    986995        }
     
    989998    function update_all_feeds() {
    990999        $links = get_bookmarks();
    991         if (empty($links)) return;
     1000        if ( empty( $links ) ) return;
    9921001
    9931002        $now = time();
    994         $this->logger->debug('START %s', current_time('mysql'));
    995         foreach ($links as $link) {
    996             $this->update_feed($link);
    997         }
    998         $this->logger->debug('END %s - elapsed %ds', current_time('mysql'), time()-$now);
     1003        $this->logger->debug( __( 'START %s', 'planetplanet' ), current_time('mysql') );
     1004        foreach ( $links as $link ) {
     1005            $this->update_feed( $link );
     1006        }
     1007        $this->logger->debug( __( 'END %s - elapsed %ds', 'planetplanet' ), current_time( 'mysql' ), time() - $now );
    9991008    }
    10001009
     
    10071016
    10081017    function purge_posts() {
    1009         $limit = $this->get_option('retain_limit');
    1010         if (!$limit) return;
    1011         if (!$this->safe_datetime($limit)) return;
     1018        $limit = $this->get_option( 'retain_limit' );
     1019        if ( !$limit ) return;
     1020        if ( !$this->safe_datetime( $limit ) ) return;
    10121021
    10131022        // Query to find some of the oldest posts before the retain limit
     
    10201029        ];
    10211030
    1022         while (!empty($posts = get_posts($query))) {
    1023             foreach ($posts as $post) {
    1024                 $this->logger->debug('Found post %4d %s %s', $post->ID, $post->post_date, $post->post_title);
     1031        while ( !empty( $posts = get_posts( $query ) ) ) {
     1032            foreach ( $posts as $post ) {
     1033                $this->logger->debug( __( 'Found post %4d %s %s', 'planetplanet' ),
     1034                                      $post->ID, $post->post_date, $post->post_title );
    10251035
    10261036                $image_id = get_post_thumbnail_id($post->ID);
    1027                 if ($image_id) {
    1028                     $image = get_post($image_id);
    1029                     $this->logger->debug('> found image %4d %s %s', $image_id, $image->post_date, $image->post_title);
    1030 
    1031                     if ($image) {
    1032                         $image_posts = get_posts([
     1037                if ( $image_id ) {
     1038                    $image = get_post( $image_id );
     1039                    $this->logger->debug( __( '> found image %4d %s %s', 'planetplanet' ),
     1040                                          $image_id, $image->post_date, $image->post_title );
     1041
     1042                    if ( $image ) {
     1043                        $image_posts = get_posts( [
    10331044                            'meta_key' => '_thumbnail_id',
    10341045                            'meta_value' => $image_id,
    10351046                            'numberposts' => -1,
    1036                         ]);
    1037 
    1038                         $this->logger->debug('>> image is attached to %d posts', count($image_posts));
     1047                        ] );
     1048
     1049                        $this->logger->debug( __( '>> image is attached to %d posts', 'planetplanet' ),
     1050                                              count($image_posts) );
    10391051
    10401052                        // Delete image only if not in use by other posts
    1041                         if (1 == count($image_posts)) {
    1042                             if (wp_delete_attachment($image_id, true))
    1043                                 $this->logger->message('Deleted image %d - %s', $image_id, $image->post_title);
     1053                        if ( 1 == count( $image_posts ) ) {
     1054                            if ( wp_delete_attachment( $image_id, true ) )
     1055                                $this->logger->message( __( 'Deleted image %d - %s', 'planetplanet' ),
     1056                                                        $image_id, $image->post_title );
    10441057                            else
    1045                                 $this->logger->error('Deletion of image %d - %s failed', $image_id, $image->post_title);
     1058                                $this->logger->error( __( 'Deletion of image %d - %s failed', 'planetplanet' ),
     1059                                                      $image_id, $image->post_title );
    10461060                        }
    10471061                    }
    10481062                }
    10491063
    1050                 if (wp_delete_post($post->ID, true))
    1051                     $this->logger->message('Deleted post %d - %s', $post->ID, $post->post_title);
     1064                if ( wp_delete_post( $post->ID, true ) )
     1065                    $this->logger->message( __( 'Deleted post %d - %s', 'planetplanet' ),
     1066                                            $post->ID, $post->post_title );
    10521067                else
    1053                     $this->logger->error('Deletion of post %d - %s failed', $post->ID, $post->post_title);
     1068                    $this->logger->error( __( 'Deletion of post %d - %s failed', 'planetplanet' ),
     1069                                          $post->ID, $post->post_title );
    10541070            }
    10551071        }
  • planetplanet/trunk/readme.txt

    r2651218 r2651566  
    11=== PlanetPlanet ===
    22Contributors: seindal
    3 Donate Link: https://www.seindal.dk/
    43Tags: rss-aggregator
    54Requires at least: 5.8
     
    109License URI: https://www.gnu.org/licenses/gpl-2.0.html
    1110
    12 Convert a wordpress site into an RSS/Atom feed aggregator like the old 'planet' software.
     11Convert a WordPress site into an RSS/Atom feed aggregator like the old 'planet' software.
    1312
    1413== Description ==
    1514
    16 The PlanetPlanet plugin will convert a wordpress site into an RSS/Atom feed aggregator by regularly reading all the configured feeds and importing the posts in the feeds to Wordpress posts.
     15The PlanetPlanet plugin will convert a WordPress site into an RSS/Atom feed aggregator by regularly reading all the configured feeds and importing the items in the feeds to WordPress posts.
    1716
    18 The feeds are registered in the old Wordpress links/bookmarks section, which is automatically reactivated. Feeds can be added, modified and deleted there.
     17The feeds are registered in the old WordPress links/bookmarks section, which is automatically reactivated. Feeds can be added, modified and deleted there.
    1918
    2019The imported posts contain title, excerpt and maybe content from the feed items. Additional custom fields are added with some data that doesn't intuitively map to WP posts. If the feed item has a featured image, that is imported too.
     
    2827Importing and purging articles can be scheduled using wp-cron. Output from scheduled actions can be mailed.
    2928
    30 The plugin adds a WP-CLI command 'planet' with subcommands for listing feeds, adding feeds, updating individual or all feeds, purging posts, and scanning web pages for available feeds. This allows most adminstration and actions to be run without using wp-cron.
     29The plugin adds a WP-CLI command 'planet' with sub-commands for listing feeds, adding feeds, updating individual or all feeds, purging posts, and scanning web pages for available feeds. This allows most administration and actions to be run without using wp-cron.
    3130
    32 Imlementation notes: feeds errors are counted in the link_rating field, and the feed is marked not visible if it generates too many errors.
     31Implementation notes: feeds errors are counted in the link_rating field, and the feed is marked not visible if it generates too many errors.
    3332
    3433== Installation ==
     
    4039== Configuration ==
    4140
    42 The plugin adds a 'Planet Planet' submenu under Settings.
     41The plugin adds a 'Planet Planet' sub-menu under Settings.
    4342
    4443* How often to check feeds: the choices are from the WP scheduler. 'None' means no automatic updates. The site can still be updated through the WP-CLI interface.
     
    4645* Discard posts older than this: the value can be anything the PHP class DateTime can parse into a past date, which includes values like '6 months ago'. Too old posts are never imported, and they're purged automatically. If the field is empty, even very old feed items are imported and never purged.
    4746
    48 * Number of errors before feed is suspended: see below
     47* Number of errors before feed is suspended: see below.
    4948
    5049* Email for updates: insert an email if you want the output from schedule actions (updates and purges) mailed to you. Leave empty for no mails.
     
    5655* User-Agent: some servers filter on the User-Agent header.
    5756
     57== How to setup an RSS feed aggregator site ==
     58
     591. Setup and configure an empty WordPress site
     602. Install and activate the PlanetPlanet plugin
     613. Setup automatic updates either through the plugin configuration page or externally through WP-CLI.
     624. Add links in the "Links" section on the right hand admin menu. You need to add Link name, URL and RSS URL for each feed.
     635. Find or create a WP theme that shows the posts the way you want, remembering that certain links will redirect automatically to the originating site of the posts.
     64
    5865== Feed errors ==
    5966
     
    6269If a feed generates too many (configurable) consecutive errors, it is marked as 'not visible'. It will not be updated any more. It can always be reactivated in the links manager.
    6370
    64 Old posts from a disabled feed are not removed. They can be easily identifed through the post category for the feed.
     71Old posts from a disabled or deleted feed are not removed. They can be easily identified through the post category for the feed.
    6572
    66 The error count and the saved error message are reset with each succesful update.
     73The error count and the saved error message are reset with each successful update.
    6774
    6875== Frequently Asked Questions ==
     
    8188== Screenshots ==
    8289
    83 The only visible part of this plugin is the setttings submenu.
     90The only visible part of this plugin is the settings sub-menu.
Note: See TracChangeset for help on using the changeset viewer.