Plugin Directory

Changeset 3336321


Ignore:
Timestamp:
07/30/2025 05:09:58 AM (8 months ago)
Author:
hideokamoto
Message:

v7.0.0

Location:
c3-cloudfront-clear-cache
Files:
6 added
4 deleted
36 edited
9 copied

Legend:

Unmodified
Added
Removed
  • c3-cloudfront-clear-cache/tags/7.0.0/c3-cloudfront-clear-cache.php

    r3309497 r3336321  
    22/**
    33 * Plugin Name: C3 Cloudfront Cache Controller
    4  * Version: 6.1.7
     4 * Version: 7.0.0
    55 * Plugin URI:https://github.com/amimoto-ami/c3-cloudfront-clear-cache
    66 * Description: Manage CloudFront Cache and provide some fixtures.
     
    1616 * Load the class loader
    1717 */
    18 require_once( __DIR__ . '/loader.php' );
     18require_once __DIR__ . '/loader.php';
    1919
    2020use C3_CloudFront_Cache_Controller\WP;
     
    2222
    2323/**
    24  * Load AWS SDK and classes
     24 * Load classes and initialize services
    2525 */
    2626function c3_init() {
    27     if ( ! class_exists( '\\Aws\\CloudFront\\CloudFrontClient' ) ) {
    28         require_once __DIR__ . '/vendor/autoload.php';
    29     }
    3027    new C3_CloudFront_Cache_Controller\Invalidation_Service();
    3128    new C3_CloudFront_Cache_Controller\Cron_Service();
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/AWS/CloudFront_Service.php

    r3309497 r3336321  
    1313}
    1414
    15 use Aws\Exception\AwsException;
    1615use C3_CloudFront_Cache_Controller\WP;
    17 use Aws\CloudFront\CloudFrontClient;
    1816
    1917/**
     
    7472
    7573    /**
    76      * Create the AWS SDK credential
     74     * Get AWS credentials
    7775     *
    7876     * @param string $access_key AWS access key id.
    7977     * @param string $secret_key AWS secret access key id.
    80      */
    81     public function create_credential( string $access_key = null, string $secret_key = null ) {
     78     * @return array|null Array with 'key', 'secret', and optionally 'token' or null if not available.
     79     */
     80    public function get_credentials( ?string $access_key = null, ?string $secret_key = null ) {
    8281        $key    = isset( $access_key ) ? $access_key : $this->env->get_aws_access_key();
    8382        $secret = isset( $secret_key ) ? $secret_key : $this->env->get_aws_secret_key();
    84         if ( ! isset( $key ) || ! isset( $secret ) ) {
    85             return null;
    86         }
    87         return new \Aws\Credentials\Credentials( $key, $secret );
     83
     84        if ( $key && $secret ) {
     85            return array(
     86                'key'    => $key,
     87                'secret' => $secret,
     88            );
     89        }
     90
     91        if ( $this->should_use_instance_role() ) {
     92            $metadata_service = new EC2_Metadata_Service();
     93            $instance_creds   = $metadata_service->get_instance_credentials();
     94
     95            if ( $instance_creds ) {
     96                return array(
     97                    'key'    => $instance_creds['key'],
     98                    'secret' => $instance_creds['secret'],
     99                    'token'  => $instance_creds['token'],
     100                );
     101            }
     102        }
     103
     104        return null;
     105    }
     106
     107    /**
     108     * Check if should use EC2 instance role
     109     *
     110     * @return bool
     111     */
     112    private function should_use_instance_role() {
     113        if ( $this->hook_service->apply_filters( 'c3_has_ec2_instance_role', false ) ) {
     114            return true;
     115        }
     116
     117        $metadata_service = new EC2_Metadata_Service();
     118        return $metadata_service->is_ec2_instance();
    88119    }
    89120
     
    97128     * @return \WP_Error|null  Return WP_Error if AWS API returns any error.
    98129     */
    99     public function try_to_call_aws_api( string $distribution_id, string $access_key = null, string $secret_key = null ) {
    100         $credentials = $this->create_credential( $access_key, $secret_key );
    101         $params      = array(
    102             'version' => 'latest',
    103             'region'  => 'us-east-1',
    104         );
    105         if ( isset( $credentials ) ) {
    106             $params['credentials'] = $credentials;
    107         }
    108         $cloudfront = CloudFrontClient::factory( $params );
    109         try {
    110             $cloudfront->getDistribution(
    111                 array(
    112                     'Id' => $distribution_id,
    113                 )
    114             );
    115             return null;
    116         } catch ( \Exception $e ) {
    117             if ( $e instanceof AwsException && 'NoSuchDistribution' === $e->getAwsErrorCode() ) {
    118                 $e = new \WP_Error( 'C3 Auth Error', "Can not find CloudFront Distribution ID: {$distribution_id} is not found." );
    119             } elseif ( $e instanceof AwsException && 'InvalidClientTokenId' === $e->getAwsErrorCode() ) {
    120                 $e = new \WP_Error( 'C3 Auth Error', 'AWS AWS Access Key or AWS Secret Key is invalid.' );
     130    public function try_to_call_aws_api( string $distribution_id, ?string $access_key = null, ?string $secret_key = null ) {
     131        $credentials = $this->get_credentials( $access_key, $secret_key );
     132        if ( ! $credentials ) {
     133            return new \WP_Error( 'C3 Auth Error', 'AWS credentials are not available.' );
     134        }
     135
     136        $session_token = isset( $credentials['token'] ) ? $credentials['token'] : null;
     137        $client        = new CloudFront_HTTP_Client( $credentials['key'], $credentials['secret'], null, $session_token );
     138        $result        = $client->get_distribution( $distribution_id );
     139
     140        if ( is_wp_error( $result ) ) {
     141            $error_message = $result->get_error_message();
     142            $error_code    = $result->get_error_code();
     143
     144            if ( $error_code === 'cloudfront_api_error' ) {
     145                if ( strpos( $error_message, 'NoSuchDistribution' ) !== false ) {
     146                    $e = new \WP_Error( 'C3 Auth Error', "Can not find CloudFront Distribution ID: {$distribution_id} is not found." );
     147                } elseif ( strpos( $error_message, 'InvalidClientTokenId' ) !== false || strpos( $error_message, 'SignatureDoesNotMatch' ) !== false ) {
     148                    $e = new \WP_Error( 'C3 Auth Error', 'AWS Access Key or AWS Secret Key is invalid.' );
     149                } else {
     150                    $e = new \WP_Error( 'C3 Auth Error', $error_message );
     151                }
    121152            } else {
    122                 $e = new \WP_Error( 'C3 Auth Error', $e->getMessage() );
    123             }
    124             error_log( print_r( $e->get_error_messages(), true ), 0 );
     153                $e = new \WP_Error( 'C3 Auth Error', $error_message );
     154            }
     155
     156            if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     157                error_log( 'C3 CloudFront Auth Error: ' . $error_message );
     158            }
    125159            return $e;
    126160        }
    127     }
    128 
    129     /**
    130      * Create CloudFront Client
     161        return null;
     162    }
     163
     164    /**
     165     * Create CloudFront HTTP Client
    131166     */
    132167    public function create_client() {
     
    137172        $options = $this->options_service->get_options();
    138173        if ( ! $options ) {
    139             return new \WP_Error( 'C3 Create Client Error', 'General setting params not defined.' );
     174            $credentials = $this->get_credentials();
     175            if ( $credentials ) {
     176                $session_token = isset( $credentials['token'] ) ? $credentials['token'] : null;
     177                $client        = new CloudFront_HTTP_Client( $credentials['key'], $credentials['secret'], null, $session_token );
     178                return $client;
     179            }
     180            return new \WP_Error( 'C3 Create Client Error', 'AWS credentials are required.' );
    140181        }
    141182
     
    152193
    153194        /**
    154          * Should use us-east-1 region, because CloudFront resources are always in there.
    155          */
    156         $params = array(
    157             'version' => 'latest',
    158             'region'  => 'us-east-1',
    159         );
    160 
    161         /**
    162          * If AWS credentials are available, will put it.
    163          */
    164         if ( $options['access_key'] && $options['secret_key'] ) {
    165             $params['credentials'] = $credentials;
    166         }
    167 
    168         /**
    169          * You can overwrite the CloudFront client constructor parameters
    170          */
    171         $this->hook_service->apply_filters( 'c3_cloudfront_client_constructor', $params );
    172 
    173         $cloudfront = CloudFrontClient::factory( $params );
    174         return $cloudfront;
     195         * If AWS credentials are available, create HTTP client.
     196         */
     197        if ( $credentials['key'] && $credentials['secret'] ) {
     198            $session_token = isset( $credentials['token'] ) ? $credentials['token'] : null;
     199            $client        = new CloudFront_HTTP_Client( $credentials['key'], $credentials['secret'], null, $session_token );
     200            return $client;
     201        }
     202
     203        $fallback_credentials = $this->get_credentials();
     204        if ( $fallback_credentials ) {
     205            $session_token = isset( $fallback_credentials['token'] ) ? $fallback_credentials['token'] : null;
     206            $client        = new CloudFront_HTTP_Client( $fallback_credentials['key'], $fallback_credentials['secret'], null, $session_token );
     207            return $client;
     208        }
     209
     210        return new \WP_Error( 'C3 Create Client Error', 'AWS credentials are required.' );
    175211    }
    176212
     
    208244        try {
    209245            $client = $this->create_client();
    210             $result = $client->createInvalidation( $params );
     246            if ( is_wp_error( $client ) ) {
     247                return $client;
     248            }
     249
     250        $distribution_id = $params['DistributionId'];
     251        $paths           = $params['InvalidationBatch']['Paths']['Items'];
     252
     253        if ( $this->hook_service->apply_filters( 'c3_log_invalidation_params', false ) ) {
     254            error_log( 'C3 CloudFront Invalidation Request - Distribution ID: ' . $distribution_id );
     255            error_log( 'C3 CloudFront Invalidation Request - Paths: ' . print_r( $paths, true ) );
     256            error_log( 'C3 CloudFront Invalidation Request - Full Params: ' . print_r( $params, true ) );
     257        }
     258
     259        $result = $client->create_invalidation( $distribution_id, $paths );
    211260            return $result;
    212         } catch ( \Aws\CloudFront\Exception\CloudFrontException $e ) {
    213             error_log( $e->__toString(), 0 );
    214             $e = new \WP_Error( 'C3 Invalidation Error', $e->__toString() );
    215             return $e;
    216261        } catch ( \Exception $e ) {
    217262            $e = new \WP_Error( 'C3 Invalidation Error', $e->getMessage() );
     
    229274    public function list_invalidations() {
    230275        try {
    231             $client          = $this->create_client();
     276            $client = $this->create_client();
     277            if ( is_wp_error( $client ) ) {
     278                error_log( 'C3 CloudFront: Failed to create CloudFront client: ' . $client->get_error_message() );
     279                return new \WP_Error( 'C3 List Invalidations Error', 'Failed to create CloudFront client: ' . $client->get_error_message() );
     280            }
     281
    232282            $distribution_id = $this->get_distribution_id();
    233             $lists           = $client->listInvalidations(
    234                 array(
    235                     'DistributionId' => $distribution_id,
    236                     'MaxItems'       => $this->hook_service->apply_filters( 'c3_max_invalidation_logs', 25 ),
    237                 )
    238             );
    239             if ( $lists['InvalidationList'] && $lists['InvalidationList']['Quantity'] > 0 ) {
    240                 return $lists['InvalidationList']['Items'];
    241             }
     283            error_log( 'C3 CloudFront: Listing invalidations for distribution: ' . $distribution_id );
     284
     285            $max_items = $this->hook_service->apply_filters( 'c3_max_invalidation_logs', 25 );
     286            $result    = $client->list_invalidations( $distribution_id, $max_items );
     287
     288            if ( is_wp_error( $result ) ) {
     289                $error_message = $result->get_error_message();
     290                $error_code    = $result->get_error_code();
     291
     292                if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     293                    error_log( 'C3 CloudFront: API Error: ' . $error_message );
     294                }
     295
     296                if ( $error_code === 'cloudfront_api_error' ) {
     297                    if ( strpos( $error_message, 'NoSuchDistribution' ) !== false ) {
     298                        if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     299                            error_log( 'C3 CloudFront: Distribution not found: ' . $distribution_id );
     300                        }
     301                        return new \WP_Error( 'C3 List Invalidations Error', "CloudFront Distribution ID: {$distribution_id} not found." );
     302                    } elseif ( strpos( $error_message, 'InvalidClientTokenId' ) !== false || strpos( $error_message, 'SignatureDoesNotMatch' ) !== false ) {
     303                        return new \WP_Error( 'C3 List Invalidations Error', 'AWS Access Key or AWS Secret Key is invalid.' );
     304                    } else {
     305                        return new \WP_Error( 'C3 List Invalidations Error', $error_message );
     306                    }
     307                } else {
     308                    return new \WP_Error( 'C3 List Invalidations Error', $error_message );
     309                }
     310            }
     311
     312            if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     313                error_log( 'C3 CloudFront: API response received (quantity: ' . ( isset( $result['Quantity'] ) ? $result['Quantity'] : 'unknown' ) . ')' );
     314            }
     315
     316            if ( isset( $result['Quantity'] ) && $result['Quantity'] > 0 && isset( $result['Items']['InvalidationSummary'] ) ) {
     317                error_log( 'C3 CloudFront: Found ' . $result['Quantity'] . ' invalidations' );
     318                return $result['Items']['InvalidationSummary'];
     319            }
     320
     321            error_log( 'C3 CloudFront: No invalidations found' );
    242322            return array();
    243         } catch ( \Aws\CloudFront\Exception\CloudFrontException $e ) {
    244             if ( isset( $distribution_id ) && 'NoSuchDistribution' === $e->getAwsErrorCode() ) {
    245                 error_log( $distribution_id . ' not found' );
    246             }
    247             error_log( $e->__toString(), 0 );
    248323        } catch ( \Exception $e ) {
    249             error_log( $e->__toString(), 0 );
     324            error_log( 'C3 CloudFront: Exception in list_invalidations: ' . $e->__toString() );
     325            return new \WP_Error( 'C3 List Invalidations Error', $e->getMessage() );
    250326        } catch ( \Error $e ) {
    251             error_log( $e->__toString(), 0 );
    252         }
    253         return array();
     327            error_log( 'C3 CloudFront: Error in list_invalidations: ' . $e->__toString() );
     328            return new \WP_Error( 'C3 List Invalidations Error', $e->getMessage() );
     329        }
    254330    }
    255331}
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/AWS/Invalidation_Batch.php

    r3309497 r3336321  
    4545
    4646    /**
    47      * Apply WordPress filter hook.
    48      * We can overwrite the invalidation item by manually
     47     * Apply invalidation item filter
    4948     *
    50      * @param \WP_Post $post WordPress Post object.
     49     * @param \WP_Post $post Current post.
    5150     */
    52     public function apply_invalidation_item_filter( \WP_Post $post = null ) {
     51    public function apply_invalidation_item_filter( ?\WP_Post $post = null ) {
    5352        $this->items = apply_filters( 'c3_invalidation_items', $this->items, $post );
    5453    }
     
    103102        );
    104103    }
    105 
    106104}
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/AWS/Invalidation_Batch_Service.php

    r3309497 r3336321  
    100100
    101101    /**
    102      * Invalidate by post
     102     * Create invalidation batch by post
    103103     *
    104104     * @param string   $home_url WP home url.
    105105     * @param string   $distribution_id CloudFront distribution id.
    106      * @param \WP_Post $post WP post object.
     106     * @param \WP_Post $post Target post.
    107107     */
    108     public function create_batch_by_post( string $home_url, string $distribution_id, \WP_Post $post = null ) {
     108    public function create_batch_by_post( string $home_url, string $distribution_id, ?\WP_Post $post = null ) {
    109109        $invalidation_batch = new Invalidation_Batch();
    110110        $invalidation_batch->put_invalidation_path( $home_url );
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/Cron_Service.php

    r3309497 r3336321  
    4040     */
    4141    private $debug;
     42
     43    /**
     44     * CloudFront service
     45     *
     46     * @var \C3_CloudFront_Cache_Controller\AWS\CloudFront_Service
     47     */
     48    private $cf_service;
    4249
    4350    /**
     
    111118        $result = $this->cf_service->create_invalidation( $query );
    112119        if ( $this->debug ) {
    113             error_log( print_r( $result, true ) );
     120            if ( is_wp_error( $result ) ) {
     121                error_log( 'C3 Cron: Invalidation failed: ' . $result->get_error_message() );
     122            } else {
     123                error_log( 'C3 Cron: Invalidation completed successfully' );
     124            }
    114125        }
    115126        $this->transient_service->delete_invalidation_query();
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/Invalidation_Service.php

    r3309497 r3336321  
    2121 */
    2222class Invalidation_Service {
     23    /**
     24     * CloudFront service.
     25     *
     26     * @var \C3_CloudFront_Cache_Controller\AWS\CloudFront_Service
     27     */
     28    private $cf_service;
     29
     30    /**
     31     * Admin notice service.
     32     *
     33     * @var WP\Admin_Notice
     34     */
     35    private $notice;
     36
    2337    /**
    2438     * Hook service
     
    234248        }
    235249
     250        if ( $this->hook_service->apply_filters( 'c3_log_invalidation_params', false ) ) {
     251            error_log( 'C3 Invalidation Started - Query: ' . print_r( $query, true ) );
     252            error_log( 'C3 Invalidation Started - Force: ' . ( $force ? 'true' : 'false' ) );
     253        }
     254
    236255        if ( $this->transient_service->should_regist_cron_job() && false === $force ) {
    237256            /**
     
    249268        $this->transient_service->set_invalidation_time();
    250269        $result = $this->cf_service->create_invalidation( $query );
     270       
     271        if ( $this->hook_service->apply_filters( 'c3_log_invalidation_params', false ) ) {
     272            if ( is_wp_error( $result ) ) {
     273                error_log( 'C3 Invalidation Failed: ' . $result->get_error_message() );
     274            } else {
     275                error_log( 'C3 Invalidation Completed Successfully: ' . print_r( $result, true ) );
     276            }
     277        }
     278       
    251279        if ( is_wp_error( $result ) ) {
    252280            return $result;
     
    287315
    288316    /**
    289      * Invalidate the post's caches
    290      *
    291      * @param \WP_Post $post WP_Posts.
    292      * @param boolean  $force Must run the invalidation.
    293      */
    294     public function invalidate_post_cache( \WP_Post $post = null, $force = false ) {
     317     * Invalidate post cache
     318     *
     319     * @param \WP_Post $post Target post.
     320     * @param boolean  $force Must invalidation.
     321     */
     322    public function invalidate_post_cache( ?\WP_Post $post = null, $force = false ) {
    295323        if ( ! isset( $post ) ) {
    296324            return new \WP_Error( 'C3 Invalidation Error', 'No such post' );
     
    325353    /**
    326354     * List the invalidation logs
     355     *
     356     * To enable debug logging for this method, add the following filter:
     357     * add_filter( 'c3_log_invalidation_list', '__return_true' );
     358     *
     359     * This will log detailed information about the invalidation list process
     360     * to the WordPress error log for troubleshooting purposes.
    327361     */
    328362    public function list_recent_invalidation_logs() {
     363        $options = $this->get_plugin_option();
     364        if ( is_wp_error( $options ) ) {
     365            error_log( 'C3 List Invalidation Logs Error: ' . $options->get_error_message() );
     366            return $options;
     367        }
     368
    329369        $histories = $this->cf_service->list_invalidations();
     370
     371        // デバッグログを追加
     372        if ( $this->debug || $this->hook_service->apply_filters( 'c3_log_invalidation_list', false ) ) {
     373            error_log( 'C3 Invalidation Logs Result: ' . print_r( $histories, true ) );
     374        }
     375
     376        // エラーが発生した場合はエラーを返す
     377        if ( is_wp_error( $histories ) ) {
     378            error_log( 'C3 List Invalidation Logs Error: ' . $histories->get_error_message() );
     379            return $histories;
     380        }
     381
    330382        return $histories;
    331383    }
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/Settings_Service.php

    r3309497 r3336321  
    8686     * @return \WP_Error|null
    8787     */
    88     public function update_options( string $distribution_id, string $access_key = null, string $secret_key = null ) {
     88    public function update_options( string $distribution_id, ?string $access_key = null, ?string $secret_key = null ) {
    8989        // CloudFront API call.
    9090        $error = $this->cf_service->try_to_call_aws_api( $distribution_id, $access_key, $secret_key );
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/Views/Settings.php

    r3309497 r3336321  
    4949            'amimoto_c3_add_settings',
    5050            function () {
    51                 require_once( C3_PLUGIN_PATH . '/templates/Plugin_Options.php' );
    52                 require_once( C3_PLUGIN_PATH . '/templates/Manually_Invalidation.php' );
    53                 require_once( C3_PLUGIN_PATH . '/templates/Invalidation_Logs.php' );
     51                require_once C3_PLUGIN_PATH . '/templates/Plugin_Options.php';
     52                require_once C3_PLUGIN_PATH . '/templates/Manually_Invalidation.php';
     53                require_once C3_PLUGIN_PATH . '/templates/Invalidation_Logs.php';
    5454            }
    5555        );
     
    7373            Constants::MENU_ID,
    7474            function () {
    75                 require_once( C3_PLUGIN_PATH . '/templates/Settings.php' );
     75                require_once C3_PLUGIN_PATH . '/templates/Settings.php';
    7676            }
    7777        );
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/WP/Admin_Notice.php

    r3309497 r3336321  
    2323
    2424    /**
    25      * Echo the success message
     25     * Print success message
    2626     *
    27      * @param string $message Successfull message.
    28      * @param string $code Successfull code.
     27     * @param string $message Message.
     28     * @param string $code Message code.
    2929     */
    30     public function echo_success_message( string $message, string $code = null ) {
     30    public function echo_success_message( string $message, ?string $code = null ) {
    3131        ?>
    3232        <div class='notice notice-success is-dismissible'>
     
    3434                <?php if ( isset( $code ) ) { ?>
    3535                    <b><?php echo esc_html( $code ); ?></b>
    36                 <?php }; ?>
     36                <?php } ?>
    3737                <?php echo esc_html( $message ); ?>
    3838            </p>
     
    4545
    4646    /**
    47      * Show success message
     47     * Print success message
    4848     *
    49      * @param string $message Successfull message.
    50      * @param string $code Successfull code.
     49     * @param string $message Message.
     50     * @param string $code Message code.
    5151     */
    52     public function show_admin_success( string $message, string $code = null ) {
     52    public function show_admin_success( string $message, ?string $code = null ) {
    5353        add_action(
    5454            'admin_notices',
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/WP/Environment.php

    r3309497 r3336321  
    122122        return version_compare( $supported_version, $version, '<=' );
    123123    }
    124 
    125124}
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/WP/Options_Service.php

    r3309497 r3336321  
    7777
    7878    /**
    79      * Test the requested parameter and save it
     79     * Update the options
    8080     *
    81      * @param string $distribution_id CloudFront distribution id.
    82      * @param string $access_key AWS access key id.
    83      * @param string $secret_key AWS secret access key id.
    84      * @return void
     81     * @param string $distribution_id The CloudFront Distribution ID.
     82     * @param string $access_key AWS Access Key.
     83     * @param string $secret_key AWS Secret Key.
     84     * @throws \Exception Update option failed.
    8585     */
    86     public function update_options( string $distribution_id, string $access_key = null, string $secret_key = null ) {
     86    public function update_options( string $distribution_id, ?string $access_key = null, ?string $secret_key = null ) {
    8787        $options = array(
    8888            'distribution_id' => $distribution_id,
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/WP/Post.php

    r3309497 r3336321  
    5555    public function parse_url( string $url ) {
    5656        $parsed_url = parse_url( $url );
    57         $url        = $parsed_url['scheme'] . '://' . $parsed_url['host'];
     57
     58        // Check if required components exist
     59        if ( ! isset( $parsed_url['scheme'] ) || ! isset( $parsed_url['host'] ) ) {
     60            return $url; // Return original URL if parsing failed
     61        }
     62
     63        $url = $parsed_url['scheme'] . '://' . $parsed_url['host'];
    5864        if ( isset( $parsed_url['path'] ) ) {
    5965            $url .= $parsed_url['path'];
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/WP/Transient.php

    r3309497 r3336321  
    4343
    4444    /**
    45      * Set the transient
     45     * Set transient
    4646     *
    47      * @see https://developer.wordpress.org/reference/functions/set_transient/
    48      * @param string $transient Transient key name.
    49      * @param mixed  $value Saved value.
    50      * @param int    $expiration Expiration of the transient.
     47     * @param string $transient_key Key name.
     48     * @param mixed  $value Value.
     49     * @param mixed  $expiration Cache expiration.
    5150     */
    52     public function set_transient( string $transient, $value, int $expiration = null ) {
    53         return set_transient( $transient, $value, $expiration );
     51    public function set_transient( string $transient_key, $value, ?int $expiration = null ) {
     52        return set_transient( $transient_key, $value, $expiration );
    5453    }
    5554
     
    6261
    6362    /**
    64      * Set the invalidation transient
     63     * Set invalidation flag
    6564     *
    66      * @param mixed $value Saved value.
    67      * @param int   $expiration Expiration of the transient.
     65     * @param boolean $flag Flag value.
     66     * @param integer $expiration Cache expiration.
    6867     */
    69     public function set_invalidation_transient( $value, int $expiration = null ) {
    70         return $this->set_transient( self::C3_INVALIDATION, $value, $expiration );
     68    public function set_invalidation_transient( bool $flag, ?int $expiration = null ) {
     69        return $this->set_transient( self::C3_INVALIDATION, $flag, $expiration );
    7170    }
    7271
     
    7978
    8079    /**
    81      * Set the invalidation targets
     80     * Set the invalidation target
    8281     *
    83      * @param mixed $value Saved value.
    84      * @param int   $expiration Expiration of the transient.
     82     * @param mixed $target Invalidation target.
     83     * @param mixed $expiration Cache expiration.
    8584     */
    86     public function set_invalidation_target( $value, int $expiration = null ) {
    87         return $this->set_transient( self::C3_CRON_INDALITATION_TARGET, $value, $expiration );
     85    public function set_invalidation_target( $target, ?int $expiration = null ) {
     86        return $this->set_transient( self::C3_CRON_INDALITATION_TARGET, $target, $expiration );
    8887    }
    8988
     
    9493        return $this->delete_transient( self::C3_CRON_INDALITATION_TARGET );
    9594    }
    96 
    9795}
  • c3-cloudfront-clear-cache/tags/7.0.0/classes/WP/Transient_Service.php

    r3309497 r3336321  
    173173        return $result;
    174174    }
    175 
    176175}
  • c3-cloudfront-clear-cache/tags/7.0.0/composer.json

    r3309497 r3336321  
    44  "type": "wordpress-plugin",
    55  "require": {
    6     "php": ">=7.4",
    7     "aws/aws-sdk-php": "^3.261"
     6    "php": ">=7.4"
    87  },
    98  "require-dev": {
     
    1211        "squizlabs/php_codesniffer": "*",
    1312        "wp-coding-standards/wpcs": "*",
    14         "wp-phpunit/wp-phpunit": "5.7.2",
    15         "phpunit/phpunit": "7.5.20",
    16         "yoast/phpunit-polyfills": "^1.0"
     13        "wp-phpunit/wp-phpunit": "*",
     14        "phpunit/phpunit": "^9.5.10",
     15        "yoast/phpunit-polyfills": "^1.0.1",
     16    "mockery/mockery": "^1.6",
     17    "10up/wp_mock": "^1.1"
    1718      },
    1819    "autoload": {
  • c3-cloudfront-clear-cache/tags/7.0.0/loader.php

    r3309497 r3336321  
    1111define( 'C3_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
    1212define( 'C3_PLUGIN_ROOT', __FILE__ );
    13 require_once( __DIR__ . '/classes/Class_Loader.php' );
    14 new C3_CloudFront_Cache_Controller\Class_Loader( dirname( __FILE__ ) . '/classes' );
    15 new C3_CloudFront_Cache_Controller\Class_Loader( dirname( __FILE__ ) . '/classes/WP' );
    16 new C3_CloudFront_Cache_Controller\Class_Loader( dirname( __FILE__ ) . '/classes/AWS' );
    17 new C3_CloudFront_Cache_Controller\Class_Loader( dirname( __FILE__ ) . '/classes/Views' );
     13require_once __DIR__ . '/classes/Class_Loader.php';
     14new C3_CloudFront_Cache_Controller\Class_Loader( __DIR__ . '/classes' );
     15new C3_CloudFront_Cache_Controller\Class_Loader( __DIR__ . '/classes/WP' );
     16new C3_CloudFront_Cache_Controller\Class_Loader( __DIR__ . '/classes/AWS' );
     17new C3_CloudFront_Cache_Controller\Class_Loader( __DIR__ . '/classes/Views' );
  • c3-cloudfront-clear-cache/tags/7.0.0/package.json

    r3309497 r3336321  
    11{
    22  "devDependencies": {
    3     "@wordpress/env": "4.0.5"
     3    "@wordpress/env": "8.2.0"
    44  },
    55  "name": "trunk",
    6   "version": "6.1.4",
     6  "version": "7.0.0",
    77  "main": "index.js",
    88  "directories": {
     
    1111  "dependencies": {},
    1212  "scripts": {
    13     "test": "wp-env run phpunit \"phpunit -c /var/www/html/wp-content/plugins/trunk/phpunit.xml --verbose\"",
     13    "test": "wp-env run --env-cwd='wp-content/plugins/c3-cloudfront-clear-cache' tests-wordpress vendor/bin/phpunit -c phpunit.xml --verbose",
    1414    "dev": "wp-env start",
    15     "wpenv": "wp-env"
     15    "wpenv": "wp-env",
     16    "composer": "wp-env run --env-cwd='wp-content/plugins/c3-cloudfront-clear-cache' tests-wordpress composer",
     17    "composer:install": "wp-env run --env-cwd='wp-content/plugins/c3-cloudfront-clear-cache' tests-wordpress composer install",
     18    "composer:update": "wp-env run --env-cwd='wp-content/plugins/c3-cloudfront-clear-cache' tests-wordpress composer update"
     19  },
     20  "wp-env": {
     21    "plugin-dir": "c3-cloudfront-clear-cache",
     22    "plugin-name": "c3-cloudfront-clear-cache",
     23    "welcome-build-command": "npm run dev"
    1624  },
    1725  "repository": {
  • c3-cloudfront-clear-cache/tags/7.0.0/readme.txt

    r3309497 r3336321  
    44Tags: AWS,CDN,CloudFront
    55Requires at least: 4.9.0
    6 Tested up to: 6.7.2
    7 Stable tag: 6.1.7
     6Tested up to: 6.8.1
     7Stable tag: 7.0.0
    88License: GPLv3 or later
    99License URI: http://www.gnu.org/licenses/gpl-3.0.html
     
    9090If post published,this plugin post invalidation request to CloudFront.
    9191
    92 = Can we select AWS SDK version ? =
    93 
    94 You can select AWS SDK version to add a plugin like ...
    95 
    96 `
    97 <?php
    98 /*
    99  * Plugin Name: Should use AWS SDK v2
    100  * Version: 0.0.1
    101  * Plugin URI:https://github.com/amimoto-ami/c3-cloudfront-clear-cache
    102  * Description: To use aws sdk v2 for C3 Cloudfront Cache Controller
    103  * Author: hideokamoto
    104  * Author URI: https://wp-kyoto.net/
    105  */
    106 add_filter( 'c3_select_aws_sdk', function() {
    107     return true;
    108 } );
    109 `
     92= Custom Implementation =
     93
     94This plugin now uses a custom AWS CloudFront implementation instead of the official AWS SDK to reduce dependencies and improve performance.
    11095
    11196== Changelog ==
     97
     98== 7.0.0 ==
     99* [Breaking Change] Remove AWS SDK dependency and implement custom HTTP CloudFront API client
     100* [Update] Add comprehensive invalidation logging with c3_log_invalidation_list filter
     101* [Update] Add configurable CloudFront region and HTTP timeout settings
     102
     103== 6.1.6 ==
     104* [Fix] Fixed PHP 8 syntax errors by adding nullable type hints
     105* [Fix] Fixed deprecation warnings about creation of dynamic properties in Invalidation_Service.php
     106* [Fix] Fixed deprecation warnings about creation of dynamic properties in Cron_Service.php
     107* [Fix] Fixed PHP 7.4 syntax errors in test files
    112108
    113109== 6.1.5 ==
  • c3-cloudfront-clear-cache/tags/7.0.0/templates/Invalidation_Logs.php

    r3309497 r3336321  
    2323$invalidation_service = new Invalidation_Service();
    2424$histories            = $invalidation_service->list_recent_invalidation_logs();
     25
     26// エラーハンドリングを追加
     27if ( is_wp_error( $histories ) ) {
     28    $error_message = $histories->get_error_message();
     29    ?>
     30    <div class="notice notice-error">
     31        <p><strong><?php _e( 'Error loading invalidation logs:', $text_domain ); ?></strong> <?php echo esc_html( $error_message ); ?></p>
     32    </div>
     33    <?php
     34    return;
     35}
    2536
    2637?>
  • c3-cloudfront-clear-cache/tags/7.0.0/templates/Settings.php

    r3309497 r3336321  
    2020?>
    2121<?php
    22 require_once( C3_PLUGIN_PATH . '/templates/Plugin_Options.php' );
    23 require_once( C3_PLUGIN_PATH . '/templates/Manually_Invalidation.php' );
    24 require_once( C3_PLUGIN_PATH . '/templates/Invalidation_Logs.php' );
     22require_once C3_PLUGIN_PATH . '/templates/Plugin_Options.php';
     23require_once C3_PLUGIN_PATH . '/templates/Manually_Invalidation.php';
     24require_once C3_PLUGIN_PATH . '/templates/Invalidation_Logs.php';
    2525
    2626?>
  • c3-cloudfront-clear-cache/tags/7.0.0/uninstall.php

    r3309497 r3336321  
    1111 * Load classes
    1212 */
    13 require_once( __DIR__ . '/loader.php' );
     13require_once __DIR__ . '/loader.php';
    1414use C3_CloudFront_Cache_Controller\WP;
    1515if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
  • c3-cloudfront-clear-cache/trunk/c3-cloudfront-clear-cache.php

    r3309497 r3336321  
    22/**
    33 * Plugin Name: C3 Cloudfront Cache Controller
    4  * Version: 6.1.7
     4 * Version: 7.0.0
    55 * Plugin URI:https://github.com/amimoto-ami/c3-cloudfront-clear-cache
    66 * Description: Manage CloudFront Cache and provide some fixtures.
     
    1616 * Load the class loader
    1717 */
    18 require_once( __DIR__ . '/loader.php' );
     18require_once __DIR__ . '/loader.php';
    1919
    2020use C3_CloudFront_Cache_Controller\WP;
     
    2222
    2323/**
    24  * Load AWS SDK and classes
     24 * Load classes and initialize services
    2525 */
    2626function c3_init() {
    27     if ( ! class_exists( '\\Aws\\CloudFront\\CloudFrontClient' ) ) {
    28         require_once __DIR__ . '/vendor/autoload.php';
    29     }
    3027    new C3_CloudFront_Cache_Controller\Invalidation_Service();
    3128    new C3_CloudFront_Cache_Controller\Cron_Service();
  • c3-cloudfront-clear-cache/trunk/classes/AWS/CloudFront_Service.php

    r3309497 r3336321  
    1313}
    1414
    15 use Aws\Exception\AwsException;
    1615use C3_CloudFront_Cache_Controller\WP;
    17 use Aws\CloudFront\CloudFrontClient;
    1816
    1917/**
     
    7472
    7573    /**
    76      * Create the AWS SDK credential
     74     * Get AWS credentials
    7775     *
    7876     * @param string $access_key AWS access key id.
    7977     * @param string $secret_key AWS secret access key id.
    80      */
    81     public function create_credential( string $access_key = null, string $secret_key = null ) {
     78     * @return array|null Array with 'key', 'secret', and optionally 'token' or null if not available.
     79     */
     80    public function get_credentials( ?string $access_key = null, ?string $secret_key = null ) {
    8281        $key    = isset( $access_key ) ? $access_key : $this->env->get_aws_access_key();
    8382        $secret = isset( $secret_key ) ? $secret_key : $this->env->get_aws_secret_key();
    84         if ( ! isset( $key ) || ! isset( $secret ) ) {
    85             return null;
    86         }
    87         return new \Aws\Credentials\Credentials( $key, $secret );
     83
     84        if ( $key && $secret ) {
     85            return array(
     86                'key'    => $key,
     87                'secret' => $secret,
     88            );
     89        }
     90
     91        if ( $this->should_use_instance_role() ) {
     92            $metadata_service = new EC2_Metadata_Service();
     93            $instance_creds   = $metadata_service->get_instance_credentials();
     94
     95            if ( $instance_creds ) {
     96                return array(
     97                    'key'    => $instance_creds['key'],
     98                    'secret' => $instance_creds['secret'],
     99                    'token'  => $instance_creds['token'],
     100                );
     101            }
     102        }
     103
     104        return null;
     105    }
     106
     107    /**
     108     * Check if should use EC2 instance role
     109     *
     110     * @return bool
     111     */
     112    private function should_use_instance_role() {
     113        if ( $this->hook_service->apply_filters( 'c3_has_ec2_instance_role', false ) ) {
     114            return true;
     115        }
     116
     117        $metadata_service = new EC2_Metadata_Service();
     118        return $metadata_service->is_ec2_instance();
    88119    }
    89120
     
    97128     * @return \WP_Error|null  Return WP_Error if AWS API returns any error.
    98129     */
    99     public function try_to_call_aws_api( string $distribution_id, string $access_key = null, string $secret_key = null ) {
    100         $credentials = $this->create_credential( $access_key, $secret_key );
    101         $params      = array(
    102             'version' => 'latest',
    103             'region'  => 'us-east-1',
    104         );
    105         if ( isset( $credentials ) ) {
    106             $params['credentials'] = $credentials;
    107         }
    108         $cloudfront = CloudFrontClient::factory( $params );
    109         try {
    110             $cloudfront->getDistribution(
    111                 array(
    112                     'Id' => $distribution_id,
    113                 )
    114             );
    115             return null;
    116         } catch ( \Exception $e ) {
    117             if ( $e instanceof AwsException && 'NoSuchDistribution' === $e->getAwsErrorCode() ) {
    118                 $e = new \WP_Error( 'C3 Auth Error', "Can not find CloudFront Distribution ID: {$distribution_id} is not found." );
    119             } elseif ( $e instanceof AwsException && 'InvalidClientTokenId' === $e->getAwsErrorCode() ) {
    120                 $e = new \WP_Error( 'C3 Auth Error', 'AWS AWS Access Key or AWS Secret Key is invalid.' );
     130    public function try_to_call_aws_api( string $distribution_id, ?string $access_key = null, ?string $secret_key = null ) {
     131        $credentials = $this->get_credentials( $access_key, $secret_key );
     132        if ( ! $credentials ) {
     133            return new \WP_Error( 'C3 Auth Error', 'AWS credentials are not available.' );
     134        }
     135
     136        $session_token = isset( $credentials['token'] ) ? $credentials['token'] : null;
     137        $client        = new CloudFront_HTTP_Client( $credentials['key'], $credentials['secret'], null, $session_token );
     138        $result        = $client->get_distribution( $distribution_id );
     139
     140        if ( is_wp_error( $result ) ) {
     141            $error_message = $result->get_error_message();
     142            $error_code    = $result->get_error_code();
     143
     144            if ( $error_code === 'cloudfront_api_error' ) {
     145                if ( strpos( $error_message, 'NoSuchDistribution' ) !== false ) {
     146                    $e = new \WP_Error( 'C3 Auth Error', "Can not find CloudFront Distribution ID: {$distribution_id} is not found." );
     147                } elseif ( strpos( $error_message, 'InvalidClientTokenId' ) !== false || strpos( $error_message, 'SignatureDoesNotMatch' ) !== false ) {
     148                    $e = new \WP_Error( 'C3 Auth Error', 'AWS Access Key or AWS Secret Key is invalid.' );
     149                } else {
     150                    $e = new \WP_Error( 'C3 Auth Error', $error_message );
     151                }
    121152            } else {
    122                 $e = new \WP_Error( 'C3 Auth Error', $e->getMessage() );
    123             }
    124             error_log( print_r( $e->get_error_messages(), true ), 0 );
     153                $e = new \WP_Error( 'C3 Auth Error', $error_message );
     154            }
     155
     156            if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     157                error_log( 'C3 CloudFront Auth Error: ' . $error_message );
     158            }
    125159            return $e;
    126160        }
    127     }
    128 
    129     /**
    130      * Create CloudFront Client
     161        return null;
     162    }
     163
     164    /**
     165     * Create CloudFront HTTP Client
    131166     */
    132167    public function create_client() {
     
    137172        $options = $this->options_service->get_options();
    138173        if ( ! $options ) {
    139             return new \WP_Error( 'C3 Create Client Error', 'General setting params not defined.' );
     174            $credentials = $this->get_credentials();
     175            if ( $credentials ) {
     176                $session_token = isset( $credentials['token'] ) ? $credentials['token'] : null;
     177                $client        = new CloudFront_HTTP_Client( $credentials['key'], $credentials['secret'], null, $session_token );
     178                return $client;
     179            }
     180            return new \WP_Error( 'C3 Create Client Error', 'AWS credentials are required.' );
    140181        }
    141182
     
    152193
    153194        /**
    154          * Should use us-east-1 region, because CloudFront resources are always in there.
    155          */
    156         $params = array(
    157             'version' => 'latest',
    158             'region'  => 'us-east-1',
    159         );
    160 
    161         /**
    162          * If AWS credentials are available, will put it.
    163          */
    164         if ( $options['access_key'] && $options['secret_key'] ) {
    165             $params['credentials'] = $credentials;
    166         }
    167 
    168         /**
    169          * You can overwrite the CloudFront client constructor parameters
    170          */
    171         $this->hook_service->apply_filters( 'c3_cloudfront_client_constructor', $params );
    172 
    173         $cloudfront = CloudFrontClient::factory( $params );
    174         return $cloudfront;
     195         * If AWS credentials are available, create HTTP client.
     196         */
     197        if ( $credentials['key'] && $credentials['secret'] ) {
     198            $session_token = isset( $credentials['token'] ) ? $credentials['token'] : null;
     199            $client        = new CloudFront_HTTP_Client( $credentials['key'], $credentials['secret'], null, $session_token );
     200            return $client;
     201        }
     202
     203        $fallback_credentials = $this->get_credentials();
     204        if ( $fallback_credentials ) {
     205            $session_token = isset( $fallback_credentials['token'] ) ? $fallback_credentials['token'] : null;
     206            $client        = new CloudFront_HTTP_Client( $fallback_credentials['key'], $fallback_credentials['secret'], null, $session_token );
     207            return $client;
     208        }
     209
     210        return new \WP_Error( 'C3 Create Client Error', 'AWS credentials are required.' );
    175211    }
    176212
     
    208244        try {
    209245            $client = $this->create_client();
    210             $result = $client->createInvalidation( $params );
     246            if ( is_wp_error( $client ) ) {
     247                return $client;
     248            }
     249
     250        $distribution_id = $params['DistributionId'];
     251        $paths           = $params['InvalidationBatch']['Paths']['Items'];
     252
     253        if ( $this->hook_service->apply_filters( 'c3_log_invalidation_params', false ) ) {
     254            error_log( 'C3 CloudFront Invalidation Request - Distribution ID: ' . $distribution_id );
     255            error_log( 'C3 CloudFront Invalidation Request - Paths: ' . print_r( $paths, true ) );
     256            error_log( 'C3 CloudFront Invalidation Request - Full Params: ' . print_r( $params, true ) );
     257        }
     258
     259        $result = $client->create_invalidation( $distribution_id, $paths );
    211260            return $result;
    212         } catch ( \Aws\CloudFront\Exception\CloudFrontException $e ) {
    213             error_log( $e->__toString(), 0 );
    214             $e = new \WP_Error( 'C3 Invalidation Error', $e->__toString() );
    215             return $e;
    216261        } catch ( \Exception $e ) {
    217262            $e = new \WP_Error( 'C3 Invalidation Error', $e->getMessage() );
     
    229274    public function list_invalidations() {
    230275        try {
    231             $client          = $this->create_client();
     276            $client = $this->create_client();
     277            if ( is_wp_error( $client ) ) {
     278                error_log( 'C3 CloudFront: Failed to create CloudFront client: ' . $client->get_error_message() );
     279                return new \WP_Error( 'C3 List Invalidations Error', 'Failed to create CloudFront client: ' . $client->get_error_message() );
     280            }
     281
    232282            $distribution_id = $this->get_distribution_id();
    233             $lists           = $client->listInvalidations(
    234                 array(
    235                     'DistributionId' => $distribution_id,
    236                     'MaxItems'       => $this->hook_service->apply_filters( 'c3_max_invalidation_logs', 25 ),
    237                 )
    238             );
    239             if ( $lists['InvalidationList'] && $lists['InvalidationList']['Quantity'] > 0 ) {
    240                 return $lists['InvalidationList']['Items'];
    241             }
     283            error_log( 'C3 CloudFront: Listing invalidations for distribution: ' . $distribution_id );
     284
     285            $max_items = $this->hook_service->apply_filters( 'c3_max_invalidation_logs', 25 );
     286            $result    = $client->list_invalidations( $distribution_id, $max_items );
     287
     288            if ( is_wp_error( $result ) ) {
     289                $error_message = $result->get_error_message();
     290                $error_code    = $result->get_error_code();
     291
     292                if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     293                    error_log( 'C3 CloudFront: API Error: ' . $error_message );
     294                }
     295
     296                if ( $error_code === 'cloudfront_api_error' ) {
     297                    if ( strpos( $error_message, 'NoSuchDistribution' ) !== false ) {
     298                        if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     299                            error_log( 'C3 CloudFront: Distribution not found: ' . $distribution_id );
     300                        }
     301                        return new \WP_Error( 'C3 List Invalidations Error', "CloudFront Distribution ID: {$distribution_id} not found." );
     302                    } elseif ( strpos( $error_message, 'InvalidClientTokenId' ) !== false || strpos( $error_message, 'SignatureDoesNotMatch' ) !== false ) {
     303                        return new \WP_Error( 'C3 List Invalidations Error', 'AWS Access Key or AWS Secret Key is invalid.' );
     304                    } else {
     305                        return new \WP_Error( 'C3 List Invalidations Error', $error_message );
     306                    }
     307                } else {
     308                    return new \WP_Error( 'C3 List Invalidations Error', $error_message );
     309                }
     310            }
     311
     312            if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     313                error_log( 'C3 CloudFront: API response received (quantity: ' . ( isset( $result['Quantity'] ) ? $result['Quantity'] : 'unknown' ) . ')' );
     314            }
     315
     316            if ( isset( $result['Quantity'] ) && $result['Quantity'] > 0 && isset( $result['Items']['InvalidationSummary'] ) ) {
     317                error_log( 'C3 CloudFront: Found ' . $result['Quantity'] . ' invalidations' );
     318                return $result['Items']['InvalidationSummary'];
     319            }
     320
     321            error_log( 'C3 CloudFront: No invalidations found' );
    242322            return array();
    243         } catch ( \Aws\CloudFront\Exception\CloudFrontException $e ) {
    244             if ( isset( $distribution_id ) && 'NoSuchDistribution' === $e->getAwsErrorCode() ) {
    245                 error_log( $distribution_id . ' not found' );
    246             }
    247             error_log( $e->__toString(), 0 );
    248323        } catch ( \Exception $e ) {
    249             error_log( $e->__toString(), 0 );
     324            error_log( 'C3 CloudFront: Exception in list_invalidations: ' . $e->__toString() );
     325            return new \WP_Error( 'C3 List Invalidations Error', $e->getMessage() );
    250326        } catch ( \Error $e ) {
    251             error_log( $e->__toString(), 0 );
    252         }
    253         return array();
     327            error_log( 'C3 CloudFront: Error in list_invalidations: ' . $e->__toString() );
     328            return new \WP_Error( 'C3 List Invalidations Error', $e->getMessage() );
     329        }
    254330    }
    255331}
  • c3-cloudfront-clear-cache/trunk/classes/AWS/Invalidation_Batch.php

    r3309497 r3336321  
    4545
    4646    /**
    47      * Apply WordPress filter hook.
    48      * We can overwrite the invalidation item by manually
     47     * Apply invalidation item filter
    4948     *
    50      * @param \WP_Post $post WordPress Post object.
     49     * @param \WP_Post $post Current post.
    5150     */
    52     public function apply_invalidation_item_filter( \WP_Post $post = null ) {
     51    public function apply_invalidation_item_filter( ?\WP_Post $post = null ) {
    5352        $this->items = apply_filters( 'c3_invalidation_items', $this->items, $post );
    5453    }
     
    103102        );
    104103    }
    105 
    106104}
  • c3-cloudfront-clear-cache/trunk/classes/AWS/Invalidation_Batch_Service.php

    r3309497 r3336321  
    100100
    101101    /**
    102      * Invalidate by post
     102     * Create invalidation batch by post
    103103     *
    104104     * @param string   $home_url WP home url.
    105105     * @param string   $distribution_id CloudFront distribution id.
    106      * @param \WP_Post $post WP post object.
     106     * @param \WP_Post $post Target post.
    107107     */
    108     public function create_batch_by_post( string $home_url, string $distribution_id, \WP_Post $post = null ) {
     108    public function create_batch_by_post( string $home_url, string $distribution_id, ?\WP_Post $post = null ) {
    109109        $invalidation_batch = new Invalidation_Batch();
    110110        $invalidation_batch->put_invalidation_path( $home_url );
  • c3-cloudfront-clear-cache/trunk/classes/Cron_Service.php

    r3309497 r3336321  
    4040     */
    4141    private $debug;
     42
     43    /**
     44     * CloudFront service
     45     *
     46     * @var \C3_CloudFront_Cache_Controller\AWS\CloudFront_Service
     47     */
     48    private $cf_service;
    4249
    4350    /**
     
    111118        $result = $this->cf_service->create_invalidation( $query );
    112119        if ( $this->debug ) {
    113             error_log( print_r( $result, true ) );
     120            if ( is_wp_error( $result ) ) {
     121                error_log( 'C3 Cron: Invalidation failed: ' . $result->get_error_message() );
     122            } else {
     123                error_log( 'C3 Cron: Invalidation completed successfully' );
     124            }
    114125        }
    115126        $this->transient_service->delete_invalidation_query();
  • c3-cloudfront-clear-cache/trunk/classes/Invalidation_Service.php

    r3309497 r3336321  
    2121 */
    2222class Invalidation_Service {
     23    /**
     24     * CloudFront service.
     25     *
     26     * @var \C3_CloudFront_Cache_Controller\AWS\CloudFront_Service
     27     */
     28    private $cf_service;
     29
     30    /**
     31     * Admin notice service.
     32     *
     33     * @var WP\Admin_Notice
     34     */
     35    private $notice;
     36
    2337    /**
    2438     * Hook service
     
    234248        }
    235249
     250        if ( $this->hook_service->apply_filters( 'c3_log_invalidation_params', false ) ) {
     251            error_log( 'C3 Invalidation Started - Query: ' . print_r( $query, true ) );
     252            error_log( 'C3 Invalidation Started - Force: ' . ( $force ? 'true' : 'false' ) );
     253        }
     254
    236255        if ( $this->transient_service->should_regist_cron_job() && false === $force ) {
    237256            /**
     
    249268        $this->transient_service->set_invalidation_time();
    250269        $result = $this->cf_service->create_invalidation( $query );
     270       
     271        if ( $this->hook_service->apply_filters( 'c3_log_invalidation_params', false ) ) {
     272            if ( is_wp_error( $result ) ) {
     273                error_log( 'C3 Invalidation Failed: ' . $result->get_error_message() );
     274            } else {
     275                error_log( 'C3 Invalidation Completed Successfully: ' . print_r( $result, true ) );
     276            }
     277        }
     278       
    251279        if ( is_wp_error( $result ) ) {
    252280            return $result;
     
    287315
    288316    /**
    289      * Invalidate the post's caches
    290      *
    291      * @param \WP_Post $post WP_Posts.
    292      * @param boolean  $force Must run the invalidation.
    293      */
    294     public function invalidate_post_cache( \WP_Post $post = null, $force = false ) {
     317     * Invalidate post cache
     318     *
     319     * @param \WP_Post $post Target post.
     320     * @param boolean  $force Must invalidation.
     321     */
     322    public function invalidate_post_cache( ?\WP_Post $post = null, $force = false ) {
    295323        if ( ! isset( $post ) ) {
    296324            return new \WP_Error( 'C3 Invalidation Error', 'No such post' );
     
    325353    /**
    326354     * List the invalidation logs
     355     *
     356     * To enable debug logging for this method, add the following filter:
     357     * add_filter( 'c3_log_invalidation_list', '__return_true' );
     358     *
     359     * This will log detailed information about the invalidation list process
     360     * to the WordPress error log for troubleshooting purposes.
    327361     */
    328362    public function list_recent_invalidation_logs() {
     363        $options = $this->get_plugin_option();
     364        if ( is_wp_error( $options ) ) {
     365            error_log( 'C3 List Invalidation Logs Error: ' . $options->get_error_message() );
     366            return $options;
     367        }
     368
    329369        $histories = $this->cf_service->list_invalidations();
     370
     371        // デバッグログを追加
     372        if ( $this->debug || $this->hook_service->apply_filters( 'c3_log_invalidation_list', false ) ) {
     373            error_log( 'C3 Invalidation Logs Result: ' . print_r( $histories, true ) );
     374        }
     375
     376        // エラーが発生した場合はエラーを返す
     377        if ( is_wp_error( $histories ) ) {
     378            error_log( 'C3 List Invalidation Logs Error: ' . $histories->get_error_message() );
     379            return $histories;
     380        }
     381
    330382        return $histories;
    331383    }
  • c3-cloudfront-clear-cache/trunk/classes/Settings_Service.php

    r3309497 r3336321  
    8686     * @return \WP_Error|null
    8787     */
    88     public function update_options( string $distribution_id, string $access_key = null, string $secret_key = null ) {
     88    public function update_options( string $distribution_id, ?string $access_key = null, ?string $secret_key = null ) {
    8989        // CloudFront API call.
    9090        $error = $this->cf_service->try_to_call_aws_api( $distribution_id, $access_key, $secret_key );
  • c3-cloudfront-clear-cache/trunk/classes/Views/Settings.php

    r3309497 r3336321  
    4949            'amimoto_c3_add_settings',
    5050            function () {
    51                 require_once( C3_PLUGIN_PATH . '/templates/Plugin_Options.php' );
    52                 require_once( C3_PLUGIN_PATH . '/templates/Manually_Invalidation.php' );
    53                 require_once( C3_PLUGIN_PATH . '/templates/Invalidation_Logs.php' );
     51                require_once C3_PLUGIN_PATH . '/templates/Plugin_Options.php';
     52                require_once C3_PLUGIN_PATH . '/templates/Manually_Invalidation.php';
     53                require_once C3_PLUGIN_PATH . '/templates/Invalidation_Logs.php';
    5454            }
    5555        );
     
    7373            Constants::MENU_ID,
    7474            function () {
    75                 require_once( C3_PLUGIN_PATH . '/templates/Settings.php' );
     75                require_once C3_PLUGIN_PATH . '/templates/Settings.php';
    7676            }
    7777        );
  • c3-cloudfront-clear-cache/trunk/classes/WP/Admin_Notice.php

    r3309497 r3336321  
    2323
    2424    /**
    25      * Echo the success message
     25     * Print success message
    2626     *
    27      * @param string $message Successfull message.
    28      * @param string $code Successfull code.
     27     * @param string $message Message.
     28     * @param string $code Message code.
    2929     */
    30     public function echo_success_message( string $message, string $code = null ) {
     30    public function echo_success_message( string $message, ?string $code = null ) {
    3131        ?>
    3232        <div class='notice notice-success is-dismissible'>
     
    3434                <?php if ( isset( $code ) ) { ?>
    3535                    <b><?php echo esc_html( $code ); ?></b>
    36                 <?php }; ?>
     36                <?php } ?>
    3737                <?php echo esc_html( $message ); ?>
    3838            </p>
     
    4545
    4646    /**
    47      * Show success message
     47     * Print success message
    4848     *
    49      * @param string $message Successfull message.
    50      * @param string $code Successfull code.
     49     * @param string $message Message.
     50     * @param string $code Message code.
    5151     */
    52     public function show_admin_success( string $message, string $code = null ) {
     52    public function show_admin_success( string $message, ?string $code = null ) {
    5353        add_action(
    5454            'admin_notices',
  • c3-cloudfront-clear-cache/trunk/classes/WP/Environment.php

    r3309497 r3336321  
    122122        return version_compare( $supported_version, $version, '<=' );
    123123    }
    124 
    125124}
  • c3-cloudfront-clear-cache/trunk/classes/WP/Options_Service.php

    r3309497 r3336321  
    7777
    7878    /**
    79      * Test the requested parameter and save it
     79     * Update the options
    8080     *
    81      * @param string $distribution_id CloudFront distribution id.
    82      * @param string $access_key AWS access key id.
    83      * @param string $secret_key AWS secret access key id.
    84      * @return void
     81     * @param string $distribution_id The CloudFront Distribution ID.
     82     * @param string $access_key AWS Access Key.
     83     * @param string $secret_key AWS Secret Key.
     84     * @throws \Exception Update option failed.
    8585     */
    86     public function update_options( string $distribution_id, string $access_key = null, string $secret_key = null ) {
     86    public function update_options( string $distribution_id, ?string $access_key = null, ?string $secret_key = null ) {
    8787        $options = array(
    8888            'distribution_id' => $distribution_id,
  • c3-cloudfront-clear-cache/trunk/classes/WP/Post.php

    r3309497 r3336321  
    5555    public function parse_url( string $url ) {
    5656        $parsed_url = parse_url( $url );
    57         $url        = $parsed_url['scheme'] . '://' . $parsed_url['host'];
     57
     58        // Check if required components exist
     59        if ( ! isset( $parsed_url['scheme'] ) || ! isset( $parsed_url['host'] ) ) {
     60            return $url; // Return original URL if parsing failed
     61        }
     62
     63        $url = $parsed_url['scheme'] . '://' . $parsed_url['host'];
    5864        if ( isset( $parsed_url['path'] ) ) {
    5965            $url .= $parsed_url['path'];
  • c3-cloudfront-clear-cache/trunk/classes/WP/Transient.php

    r3309497 r3336321  
    4343
    4444    /**
    45      * Set the transient
     45     * Set transient
    4646     *
    47      * @see https://developer.wordpress.org/reference/functions/set_transient/
    48      * @param string $transient Transient key name.
    49      * @param mixed  $value Saved value.
    50      * @param int    $expiration Expiration of the transient.
     47     * @param string $transient_key Key name.
     48     * @param mixed  $value Value.
     49     * @param mixed  $expiration Cache expiration.
    5150     */
    52     public function set_transient( string $transient, $value, int $expiration = null ) {
    53         return set_transient( $transient, $value, $expiration );
     51    public function set_transient( string $transient_key, $value, ?int $expiration = null ) {
     52        return set_transient( $transient_key, $value, $expiration );
    5453    }
    5554
     
    6261
    6362    /**
    64      * Set the invalidation transient
     63     * Set invalidation flag
    6564     *
    66      * @param mixed $value Saved value.
    67      * @param int   $expiration Expiration of the transient.
     65     * @param boolean $flag Flag value.
     66     * @param integer $expiration Cache expiration.
    6867     */
    69     public function set_invalidation_transient( $value, int $expiration = null ) {
    70         return $this->set_transient( self::C3_INVALIDATION, $value, $expiration );
     68    public function set_invalidation_transient( bool $flag, ?int $expiration = null ) {
     69        return $this->set_transient( self::C3_INVALIDATION, $flag, $expiration );
    7170    }
    7271
     
    7978
    8079    /**
    81      * Set the invalidation targets
     80     * Set the invalidation target
    8281     *
    83      * @param mixed $value Saved value.
    84      * @param int   $expiration Expiration of the transient.
     82     * @param mixed $target Invalidation target.
     83     * @param mixed $expiration Cache expiration.
    8584     */
    86     public function set_invalidation_target( $value, int $expiration = null ) {
    87         return $this->set_transient( self::C3_CRON_INDALITATION_TARGET, $value, $expiration );
     85    public function set_invalidation_target( $target, ?int $expiration = null ) {
     86        return $this->set_transient( self::C3_CRON_INDALITATION_TARGET, $target, $expiration );
    8887    }
    8988
     
    9493        return $this->delete_transient( self::C3_CRON_INDALITATION_TARGET );
    9594    }
    96 
    9795}
  • c3-cloudfront-clear-cache/trunk/classes/WP/Transient_Service.php

    r3309497 r3336321  
    173173        return $result;
    174174    }
    175 
    176175}
  • c3-cloudfront-clear-cache/trunk/composer.json

    r3309497 r3336321  
    44  "type": "wordpress-plugin",
    55  "require": {
    6     "php": ">=7.4",
    7     "aws/aws-sdk-php": "^3.261"
     6    "php": ">=7.4"
    87  },
    98  "require-dev": {
     
    1211        "squizlabs/php_codesniffer": "*",
    1312        "wp-coding-standards/wpcs": "*",
    14         "wp-phpunit/wp-phpunit": "5.7.2",
    15         "phpunit/phpunit": "7.5.20",
    16         "yoast/phpunit-polyfills": "^1.0"
     13        "wp-phpunit/wp-phpunit": "*",
     14        "phpunit/phpunit": "^9.5.10",
     15        "yoast/phpunit-polyfills": "^1.0.1",
     16    "mockery/mockery": "^1.6",
     17    "10up/wp_mock": "^1.1"
    1718      },
    1819    "autoload": {
  • c3-cloudfront-clear-cache/trunk/loader.php

    r3309497 r3336321  
    1111define( 'C3_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
    1212define( 'C3_PLUGIN_ROOT', __FILE__ );
    13 require_once( __DIR__ . '/classes/Class_Loader.php' );
    14 new C3_CloudFront_Cache_Controller\Class_Loader( dirname( __FILE__ ) . '/classes' );
    15 new C3_CloudFront_Cache_Controller\Class_Loader( dirname( __FILE__ ) . '/classes/WP' );
    16 new C3_CloudFront_Cache_Controller\Class_Loader( dirname( __FILE__ ) . '/classes/AWS' );
    17 new C3_CloudFront_Cache_Controller\Class_Loader( dirname( __FILE__ ) . '/classes/Views' );
     13require_once __DIR__ . '/classes/Class_Loader.php';
     14new C3_CloudFront_Cache_Controller\Class_Loader( __DIR__ . '/classes' );
     15new C3_CloudFront_Cache_Controller\Class_Loader( __DIR__ . '/classes/WP' );
     16new C3_CloudFront_Cache_Controller\Class_Loader( __DIR__ . '/classes/AWS' );
     17new C3_CloudFront_Cache_Controller\Class_Loader( __DIR__ . '/classes/Views' );
  • c3-cloudfront-clear-cache/trunk/package.json

    r3309497 r3336321  
    11{
    22  "devDependencies": {
    3     "@wordpress/env": "4.0.5"
     3    "@wordpress/env": "8.2.0"
    44  },
    55  "name": "trunk",
    6   "version": "6.1.4",
     6  "version": "7.0.0",
    77  "main": "index.js",
    88  "directories": {
     
    1111  "dependencies": {},
    1212  "scripts": {
    13     "test": "wp-env run phpunit \"phpunit -c /var/www/html/wp-content/plugins/trunk/phpunit.xml --verbose\"",
     13    "test": "wp-env run --env-cwd='wp-content/plugins/c3-cloudfront-clear-cache' tests-wordpress vendor/bin/phpunit -c phpunit.xml --verbose",
    1414    "dev": "wp-env start",
    15     "wpenv": "wp-env"
     15    "wpenv": "wp-env",
     16    "composer": "wp-env run --env-cwd='wp-content/plugins/c3-cloudfront-clear-cache' tests-wordpress composer",
     17    "composer:install": "wp-env run --env-cwd='wp-content/plugins/c3-cloudfront-clear-cache' tests-wordpress composer install",
     18    "composer:update": "wp-env run --env-cwd='wp-content/plugins/c3-cloudfront-clear-cache' tests-wordpress composer update"
     19  },
     20  "wp-env": {
     21    "plugin-dir": "c3-cloudfront-clear-cache",
     22    "plugin-name": "c3-cloudfront-clear-cache",
     23    "welcome-build-command": "npm run dev"
    1624  },
    1725  "repository": {
  • c3-cloudfront-clear-cache/trunk/readme.txt

    r3309497 r3336321  
    44Tags: AWS,CDN,CloudFront
    55Requires at least: 4.9.0
    6 Tested up to: 6.7.2
    7 Stable tag: 6.1.7
     6Tested up to: 6.8.1
     7Stable tag: 7.0.0
    88License: GPLv3 or later
    99License URI: http://www.gnu.org/licenses/gpl-3.0.html
     
    9090If post published,this plugin post invalidation request to CloudFront.
    9191
    92 = Can we select AWS SDK version ? =
    93 
    94 You can select AWS SDK version to add a plugin like ...
    95 
    96 `
    97 <?php
    98 /*
    99  * Plugin Name: Should use AWS SDK v2
    100  * Version: 0.0.1
    101  * Plugin URI:https://github.com/amimoto-ami/c3-cloudfront-clear-cache
    102  * Description: To use aws sdk v2 for C3 Cloudfront Cache Controller
    103  * Author: hideokamoto
    104  * Author URI: https://wp-kyoto.net/
    105  */
    106 add_filter( 'c3_select_aws_sdk', function() {
    107     return true;
    108 } );
    109 `
     92= Custom Implementation =
     93
     94This plugin now uses a custom AWS CloudFront implementation instead of the official AWS SDK to reduce dependencies and improve performance.
    11095
    11196== Changelog ==
     97
     98== 7.0.0 ==
     99* [Breaking Change] Remove AWS SDK dependency and implement custom HTTP CloudFront API client
     100* [Update] Add comprehensive invalidation logging with c3_log_invalidation_list filter
     101* [Update] Add configurable CloudFront region and HTTP timeout settings
     102
     103== 6.1.6 ==
     104* [Fix] Fixed PHP 8 syntax errors by adding nullable type hints
     105* [Fix] Fixed deprecation warnings about creation of dynamic properties in Invalidation_Service.php
     106* [Fix] Fixed deprecation warnings about creation of dynamic properties in Cron_Service.php
     107* [Fix] Fixed PHP 7.4 syntax errors in test files
    112108
    113109== 6.1.5 ==
  • c3-cloudfront-clear-cache/trunk/templates/Invalidation_Logs.php

    r3309497 r3336321  
    2323$invalidation_service = new Invalidation_Service();
    2424$histories            = $invalidation_service->list_recent_invalidation_logs();
     25
     26// エラーハンドリングを追加
     27if ( is_wp_error( $histories ) ) {
     28    $error_message = $histories->get_error_message();
     29    ?>
     30    <div class="notice notice-error">
     31        <p><strong><?php _e( 'Error loading invalidation logs:', $text_domain ); ?></strong> <?php echo esc_html( $error_message ); ?></p>
     32    </div>
     33    <?php
     34    return;
     35}
    2536
    2637?>
  • c3-cloudfront-clear-cache/trunk/templates/Settings.php

    r3309497 r3336321  
    2020?>
    2121<?php
    22 require_once( C3_PLUGIN_PATH . '/templates/Plugin_Options.php' );
    23 require_once( C3_PLUGIN_PATH . '/templates/Manually_Invalidation.php' );
    24 require_once( C3_PLUGIN_PATH . '/templates/Invalidation_Logs.php' );
     22require_once C3_PLUGIN_PATH . '/templates/Plugin_Options.php';
     23require_once C3_PLUGIN_PATH . '/templates/Manually_Invalidation.php';
     24require_once C3_PLUGIN_PATH . '/templates/Invalidation_Logs.php';
    2525
    2626?>
  • c3-cloudfront-clear-cache/trunk/uninstall.php

    r3309497 r3336321  
    1111 * Load classes
    1212 */
    13 require_once( __DIR__ . '/loader.php' );
     13require_once __DIR__ . '/loader.php';
    1414use C3_CloudFront_Cache_Controller\WP;
    1515if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
Note: See TracChangeset for help on using the changeset viewer.