Merge pull request #322 from woocommerce/pcp-271-use-psalm

Add psalm
This commit is contained in:
Emili Castells 2021-10-13 16:48:49 +02:00 committed by GitHub
commit 79e2dd2ef5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 2784 additions and 73 deletions

View file

@ -30,5 +30,8 @@ jobs:
- name: Run PHPUnit - name: Run PHPUnit
run: vendor/bin/phpunit run: vendor/bin/phpunit
- name: Psalm
run: ./vendor/bin/psalm --show-info=false --threads=8 --diff
- name: Run PHPCS - name: Run PHPCS
run: ./vendor/bin/phpcs --runtime-set ignore_warnings_on_exit 1 src modules woocommerce-paypal-payments.php --extensions=php run: ./vendor/bin/phpcs --runtime-set ignore_warnings_on_exit 1 src modules woocommerce-paypal-payments.php --extensions=php

View file

@ -21,6 +21,7 @@ PayPal's latest complete payments processing solution. Accept PayPal, Pay Later,
1. `$ composer install` 1. `$ composer install`
2. `$ ./vendor/bin/phpunit` 2. `$ ./vendor/bin/phpunit`
3. `$ ./vendor/bin/phpcs` 3. `$ ./vendor/bin/phpcs`
4. `$ ./vendor/bin/psalm`
### Docker ### Docker

View file

@ -17,7 +17,10 @@
"require-dev": { "require-dev": {
"woocommerce/woocommerce-sniffs": "^0.1.0", "woocommerce/woocommerce-sniffs": "^0.1.0",
"phpunit/phpunit": "^7.0 | ^8.0 | ^9.0", "phpunit/phpunit": "^7.0 | ^8.0 | ^9.0",
"brain/monkey": "^2.4" "brain/monkey": "^2.4",
"php-stubs/wordpress-stubs": "^5.0@stable",
"php-stubs/woocommerce-stubs": "^5.0@stable",
"vimeo/psalm": "^4.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

1546
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -219,10 +219,10 @@ return array(
'api.factory.webhook' => static function ( ContainerInterface $container ): WebhookFactory { 'api.factory.webhook' => static function ( ContainerInterface $container ): WebhookFactory {
return new WebhookFactory(); return new WebhookFactory();
}, },
'api.factory.webhook-event' => static function ( $container ): WebhookEventFactory { 'api.factory.webhook-event' => static function ( ContainerInterface $container ): WebhookEventFactory {
return new WebhookEventFactory(); return new WebhookEventFactory();
}, },
'api.factory.capture' => static function ( $container ): CaptureFactory { 'api.factory.capture' => static function ( ContainerInterface $container ): CaptureFactory {
$amount_factory = $container->get( 'api.factory.amount' ); $amount_factory = $container->get( 'api.factory.amount' );
return new CaptureFactory( $amount_factory ); return new CaptureFactory( $amount_factory );

View file

@ -164,7 +164,7 @@ class Capture {
* @return array * @return array
*/ */
public function to_array() : array { public function to_array() : array {
$data = array( $data = array(
'id' => $this->id(), 'id' => $this->id(),
'status' => $this->status()->name(), 'status' => $this->status()->name(),
'amount' => $this->amount()->to_array(), 'amount' => $this->amount()->to_array(),
@ -173,8 +173,9 @@ class Capture {
'invoice_id' => $this->invoice_id(), 'invoice_id' => $this->invoice_id(),
'custom_id' => $this->custom_id(), 'custom_id' => $this->custom_id(),
); );
if ( $this->status()->details() ) { $details = $this->status()->details();
$data['status_details'] = array( 'reason' => $this->status()->details()->reason() ); if ( $details ) {
$data['status_details'] = array( 'reason' => $details->reason() );
} }
return $data; return $data;
} }

View file

@ -40,9 +40,9 @@ class Webhook {
/** /**
* Webhook constructor. * Webhook constructor.
* *
* @param string $url The URL of the webhook. * @param string $url The URL of the webhook.
* @param string[] $event_types The associated event types. * @param stdClass[] $event_types The associated event types.
* @param string $id The id of the webhook. * @param string $id The id of the webhook.
*/ */
public function __construct( string $url, array $event_types, string $id = '' ) { public function __construct( string $url, array $event_types, string $id = '' ) {
$this->url = $url; $this->url = $url;

View file

@ -9,6 +9,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient\Factory; namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
use stdClass;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Webhook; use WooCommerce\PayPalCommerce\ApiClient\Entity\Webhook;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
@ -20,15 +21,15 @@ class WebhookFactory {
/** /**
* Returns a webhook for a URL with an array of event types associated to this URL. * Returns a webhook for a URL with an array of event types associated to this URL.
* *
* @param string $url The URL. * @param string $url The URL.
* @param array $event_types The event types to which this URL listens to. * @param string[] $event_types The event types to which this URL listens to.
* *
* @return Webhook * @return Webhook
*/ */
public function for_url_and_events( string $url, array $event_types ): Webhook { public function for_url_and_events( string $url, array $event_types ): Webhook {
$event_types = array_map( $event_types = array_map(
static function ( string $type ): array { static function ( string $type ): stdClass {
return array( 'name' => $type ); return (object) array( 'name' => $type );
}, },
$event_types $event_types
); );
@ -52,12 +53,12 @@ class WebhookFactory {
/** /**
* Returns a Webhook based of a PayPal JSON response. * Returns a Webhook based of a PayPal JSON response.
* *
* @param \stdClass $data The JSON object. * @param stdClass $data The JSON object.
* *
* @return Webhook * @return Webhook
* @throws RuntimeException When JSON object is malformed. * @throws RuntimeException When JSON object is malformed.
*/ */
public function from_paypal_response( \stdClass $data ): Webhook { public function from_paypal_response( stdClass $data ): Webhook {
if ( ! isset( $data->id ) ) { if ( ! isset( $data->id ) ) {
throw new RuntimeException( throw new RuntimeException(
__( 'No id for webhook given.', 'woocommerce-paypal-payments' ) __( 'No id for webhook given.', 'woocommerce-paypal-payments' )

View file

@ -9,6 +9,8 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Compat; namespace WooCommerce\PayPalCommerce\Compat;
use Psr\Container\ContainerInterface;
return array( return array(
'compat.ppec.mock-gateway' => static function( $container ) { 'compat.ppec.mock-gateway' => static function( $container ) {
@ -23,7 +25,7 @@ return array(
return new PPEC\MockGateway( $title ); return new PPEC\MockGateway( $title );
}, },
'compat.ppec.subscriptions-handler' => static function ( $container ) { 'compat.ppec.subscriptions-handler' => static function ( ContainerInterface $container ) {
$ppcp_renewal_handler = $container->get( 'subscription.renewal-handler' ); $ppcp_renewal_handler = $container->get( 'subscription.renewal-handler' );
$gateway = $container->get( 'compat.ppec.mock-gateway' ); $gateway = $container->get( 'compat.ppec.mock-gateway' );

View file

@ -10,7 +10,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\StatusReport; namespace WooCommerce\PayPalCommerce\StatusReport;
return array( return array(
'status-report.renderer' => static function ( $container ): Renderer { 'status-report.renderer' => static function (): Renderer {
return new Renderer(); return new Renderer();
}, },
); );

View file

@ -9,17 +9,18 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Vaulting; namespace WooCommerce\PayPalCommerce\Vaulting;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\Vaulting\Assets\MyAccountPaymentsAssets; use WooCommerce\PayPalCommerce\Vaulting\Assets\MyAccountPaymentsAssets;
use WooCommerce\PayPalCommerce\Vaulting\Endpoint\DeletePaymentTokenEndpoint; use WooCommerce\PayPalCommerce\Vaulting\Endpoint\DeletePaymentTokenEndpoint;
return array( return array(
'vaulting.module-url' => static function ( $container ): string { 'vaulting.module-url' => static function ( ContainerInterface $container ): string {
return plugins_url( return plugins_url(
'/modules/ppcp-vaulting/', '/modules/ppcp-vaulting/',
dirname( __FILE__, 3 ) . '/woocommerce-paypal-payments.php' dirname( __FILE__, 3 ) . '/woocommerce-paypal-payments.php'
); );
}, },
'vaulting.assets.myaccount-payments' => function( $container ) : MyAccountPaymentsAssets { 'vaulting.assets.myaccount-payments' => function( ContainerInterface $container ) : MyAccountPaymentsAssets {
return new MyAccountPaymentsAssets( return new MyAccountPaymentsAssets(
$container->get( 'vaulting.module-url' ) $container->get( 'vaulting.module-url' )
); );
@ -27,12 +28,12 @@ return array(
'vaulting.payment-tokens-renderer' => static function (): PaymentTokensRenderer { 'vaulting.payment-tokens-renderer' => static function (): PaymentTokensRenderer {
return new PaymentTokensRenderer(); return new PaymentTokensRenderer();
}, },
'vaulting.repository.payment-token' => static function ( $container ): PaymentTokenRepository { 'vaulting.repository.payment-token' => static function ( ContainerInterface $container ): PaymentTokenRepository {
$factory = $container->get( 'api.factory.payment-token' ); $factory = $container->get( 'api.factory.payment-token' );
$endpoint = $container->get( 'api.endpoint.payment-token' ); $endpoint = $container->get( 'api.endpoint.payment-token' );
return new PaymentTokenRepository( $factory, $endpoint ); return new PaymentTokenRepository( $factory, $endpoint );
}, },
'vaulting.endpoint.delete' => function( $container ) : DeletePaymentTokenEndpoint { 'vaulting.endpoint.delete' => function( ContainerInterface $container ) : DeletePaymentTokenEndpoint {
return new DeletePaymentTokenEndpoint( return new DeletePaymentTokenEndpoint(
$container->get( 'vaulting.repository.payment-token' ), $container->get( 'vaulting.repository.payment-token' ),
$container->get( 'button.request-data' ), $container->get( 'button.request-data' ),

View file

@ -20,15 +20,15 @@ use Psr\Log\LoggerInterface;
return array( return array(
'api.merchant_email' => static function ( $container ): string { 'api.merchant_email' => static function ( ContainerInterface $container ): string {
$settings = $container->get( 'wcgateway.settings' ); $settings = $container->get( 'wcgateway.settings' );
return $settings->has( 'merchant_email' ) ? (string) $settings->get( 'merchant_email' ) : ''; return $settings->has( 'merchant_email' ) ? (string) $settings->get( 'merchant_email' ) : '';
}, },
'api.merchant_id' => static function ( $container ): string { 'api.merchant_id' => static function ( ContainerInterface $container ): string {
$settings = $container->get( 'wcgateway.settings' ); $settings = $container->get( 'wcgateway.settings' );
return $settings->has( 'merchant_id' ) ? (string) $settings->get( 'merchant_id' ) : ''; return $settings->has( 'merchant_id' ) ? (string) $settings->get( 'merchant_id' ) : '';
}, },
'api.partner_merchant_id' => static function ( $container ): string { 'api.partner_merchant_id' => static function ( ContainerInterface $container ): string {
$environment = $container->get( 'onboarding.environment' ); $environment = $container->get( 'onboarding.environment' );
/** /**
@ -39,20 +39,20 @@ return array(
return $environment->current_environment_is( Environment::SANDBOX ) ? return $environment->current_environment_is( Environment::SANDBOX ) ?
(string) $container->get( 'api.partner_merchant_id-sandbox' ) : (string) $container->get( 'api.partner_merchant_id-production' ); (string) $container->get( 'api.partner_merchant_id-sandbox' ) : (string) $container->get( 'api.partner_merchant_id-production' );
}, },
'api.key' => static function ( $container ): string { 'api.key' => static function ( ContainerInterface $container ): string {
$settings = $container->get( 'wcgateway.settings' ); $settings = $container->get( 'wcgateway.settings' );
$key = $settings->has( 'client_id' ) ? (string) $settings->get( 'client_id' ) : ''; $key = $settings->has( 'client_id' ) ? (string) $settings->get( 'client_id' ) : '';
return $key; return $key;
}, },
'api.secret' => static function ( $container ): string { 'api.secret' => static function ( ContainerInterface $container ): string {
$settings = $container->get( 'wcgateway.settings' ); $settings = $container->get( 'wcgateway.settings' );
return $settings->has( 'client_secret' ) ? (string) $settings->get( 'client_secret' ) : ''; return $settings->has( 'client_secret' ) ? (string) $settings->get( 'client_secret' ) : '';
}, },
'api.prefix' => static function ( $container ): string { 'api.prefix' => static function ( ContainerInterface $container ): string {
$settings = $container->get( 'wcgateway.settings' ); $settings = $container->get( 'wcgateway.settings' );
return $settings->has( 'prefix' ) ? (string) $settings->get( 'prefix' ) : 'WC-'; return $settings->has( 'prefix' ) ? (string) $settings->get( 'prefix' ) : 'WC-';
}, },
'api.endpoint.order' => static function ( $container ): OrderEndpoint { 'api.endpoint.order' => static function ( ContainerInterface $container ): OrderEndpoint {
$order_factory = $container->get( 'api.factory.order' ); $order_factory = $container->get( 'api.factory.order' );
$patch_collection_factory = $container->get( 'api.factory.patch-collection-factory' ); $patch_collection_factory = $container->get( 'api.factory.patch-collection-factory' );
$logger = $container->get( 'woocommerce.logger.woocommerce' ); $logger = $container->get( 'woocommerce.logger.woocommerce' );
@ -85,7 +85,7 @@ return array(
$bn_code $bn_code
); );
}, },
'woocommerce.logger.woocommerce' => function ( $container ): LoggerInterface { 'woocommerce.logger.woocommerce' => function ( ContainerInterface $container ): LoggerInterface {
$settings = $container->get( 'wcgateway.settings' ); $settings = $container->get( 'wcgateway.settings' );
if ( ! function_exists( 'wc_get_logger' ) || ! $settings->has( 'logging_enabled' ) || ! $settings->get( 'logging_enabled' ) ) { if ( ! function_exists( 'wc_get_logger' ) || ! $settings->has( 'logging_enabled' ) || ! $settings->get( 'logging_enabled' ) ) {
return new NullLogger(); return new NullLogger();

View file

@ -113,13 +113,13 @@ return array(
$settings = $container->get( 'wcgateway.settings' ); $settings = $container->get( 'wcgateway.settings' );
return new DisableGateways( $session_handler, $settings ); return new DisableGateways( $session_handler, $settings );
}, },
'wcgateway.is-wc-payments-page' => static function ( $container ): bool { 'wcgateway.is-wc-payments-page' => static function ( ContainerInterface $container ): bool {
$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
$tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : ''; $tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : '';
return 'wc-settings' === $page && 'checkout' === $tab; return 'wc-settings' === $page && 'checkout' === $tab;
}, },
'wcgateway.is-ppcp-settings-page' => static function ( $container ): bool { 'wcgateway.is-ppcp-settings-page' => static function ( ContainerInterface $container ): bool {
if ( ! $container->get( 'wcgateway.is-wc-payments-page' ) ) { if ( ! $container->get( 'wcgateway.is-wc-payments-page' ) ) {
return false; return false;
} }
@ -128,7 +128,7 @@ return array(
return in_array( $section, array( PayPalGateway::ID, CreditCardGateway::ID, WebhooksStatusPage::ID ), true ); return in_array( $section, array( PayPalGateway::ID, CreditCardGateway::ID, WebhooksStatusPage::ID ), true );
}, },
'wcgateway.current-ppcp-settings-page-id' => static function ( $container ): string { 'wcgateway.current-ppcp-settings-page-id' => static function ( ContainerInterface $container ): string {
if ( ! $container->get( 'wcgateway.is-ppcp-settings-page' ) ) { if ( ! $container->get( 'wcgateway.is-ppcp-settings-page' ) ) {
return ''; return '';
} }
@ -155,7 +155,7 @@ return array(
return new DccWithoutPayPalAdminNotice( $state, $settings, $is_payments_page, $is_ppcp_settings_page ); return new DccWithoutPayPalAdminNotice( $state, $settings, $is_payments_page, $is_ppcp_settings_page );
}, },
'wcgateway.notice.authorize-order-action' => 'wcgateway.notice.authorize-order-action' =>
static function ( $container ): AuthorizeOrderActionNotice { static function ( ContainerInterface $container ): AuthorizeOrderActionNotice {
return new AuthorizeOrderActionNotice(); return new AuthorizeOrderActionNotice();
}, },
'wcgateway.settings.sections-renderer' => static function ( ContainerInterface $container ): SectionsRenderer { 'wcgateway.settings.sections-renderer' => static function ( ContainerInterface $container ): SectionsRenderer {
@ -1973,10 +1973,10 @@ return array(
dirname( __FILE__, 3 ) . '/woocommerce-paypal-payments.php' dirname( __FILE__, 3 ) . '/woocommerce-paypal-payments.php'
); );
}, },
'wcgateway.relative-path' => static function( $container ): string { 'wcgateway.relative-path' => static function( ContainerInterface $container ): string {
return 'modules/ppcp-wc-gateway/'; return 'modules/ppcp-wc-gateway/';
}, },
'wcgateway.absolute-path' => static function( $container ): string { 'wcgateway.absolute-path' => static function( ContainerInterface $container ): string {
return plugin_dir_path( return plugin_dir_path(
dirname( __FILE__, 3 ) . '/woocommerce-paypal-payments.php' dirname( __FILE__, 3 ) . '/woocommerce-paypal-payments.php'
) . ) .
@ -1993,15 +1993,15 @@ return array(
); );
}, },
'wcgateway.transaction-url-sandbox' => static function ( $container ): string { 'wcgateway.transaction-url-sandbox' => static function ( ContainerInterface $container ): string {
return 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s'; return 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s';
}, },
'wcgateway.transaction-url-live' => static function ( $container ): string { 'wcgateway.transaction-url-live' => static function ( ContainerInterface $container ): string {
return 'https://www.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s'; return 'https://www.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s';
}, },
'wcgateway.transaction-url-provider' => static function ( $container ): TransactionUrlProvider { 'wcgateway.transaction-url-provider' => static function ( ContainerInterface $container ): TransactionUrlProvider {
$sandbox_url_base = $container->get( 'wcgateway.transaction-url-sandbox' ); $sandbox_url_base = $container->get( 'wcgateway.transaction-url-sandbox' );
$live_url_base = $container->get( 'wcgateway.transaction-url-live' ); $live_url_base = $container->get( 'wcgateway.transaction-url-live' );
@ -2015,7 +2015,7 @@ return array(
return new DCCProductStatus( $settings, $partner_endpoint ); return new DCCProductStatus( $settings, $partner_endpoint );
}, },
'button.helper.messages-disclaimers' => static function ( $container ): MessagesDisclaimers { 'button.helper.messages-disclaimers' => static function ( ContainerInterface $container ): MessagesDisclaimers {
return new MessagesDisclaimers(); return new MessagesDisclaimers();
}, },
); );

View file

@ -55,8 +55,9 @@ trait PaymentsStatusHandlingTrait {
): void { ): void {
$status = $capture->status(); $status = $capture->status();
if ( $status->details() ) { $details = $status->details();
$this->add_status_details_note( $wc_order, $status->name(), $status->details()->text() ); if ( $details ) {
$this->add_status_details_note( $wc_order, $status->name(), $details->text() );
} }
switch ( $status->name() ) { switch ( $status->name() ) {
@ -95,8 +96,9 @@ trait PaymentsStatusHandlingTrait {
): void { ): void {
$status = $authorization->status(); $status = $authorization->status();
if ( $status->details() ) { $details = $status->details();
$this->add_status_details_note( $wc_order, $status->name(), $status->details()->text() ); if ( $details ) {
$this->add_status_details_note( $wc_order, $status->name(), $details->text() );
} }
switch ( $status->name() ) { switch ( $status->name() ) {

View file

@ -148,9 +148,9 @@ class WCGatewayModule implements ModuleInterface {
/** /**
* Registers the payment gateways. * Registers the payment gateways.
* *
* @param ContainerInterface|null $container The container. * @param ContainerInterface $container The container.
*/ */
private function register_payment_gateways( ContainerInterface $container = null ) { private function register_payment_gateways( ContainerInterface $container ) {
add_filter( add_filter(
'woocommerce_payment_gateways', 'woocommerce_payment_gateways',

View file

@ -72,7 +72,7 @@ return array(
); );
}, },
'webhook.current' => function( $container ) : ?Webhook { 'webhook.current' => function( ContainerInterface $container ) : ?Webhook {
$data = (array) get_option( WebhookRegistrar::KEY, array() ); $data = (array) get_option( WebhookRegistrar::KEY, array() );
if ( empty( $data ) ) { if ( empty( $data ) ) {
return null; return null;
@ -91,18 +91,18 @@ return array(
} }
}, },
'webhook.is-registered' => function( $container ) : bool { 'webhook.is-registered' => function( ContainerInterface $container ) : bool {
return $container->get( 'webhook.current' ) !== null; return $container->get( 'webhook.current' ) !== null;
}, },
'webhook.status.registered-webhooks' => function( $container ) : array { 'webhook.status.registered-webhooks' => function( ContainerInterface $container ) : array {
$endpoint = $container->get( 'api.endpoint.webhook' ); $endpoint = $container->get( 'api.endpoint.webhook' );
assert( $endpoint instanceof WebhookEndpoint ); assert( $endpoint instanceof WebhookEndpoint );
return $endpoint->list(); return $endpoint->list();
}, },
'webhook.status.registered-webhooks-data' => function( $container ) : array { 'webhook.status.registered-webhooks-data' => function( ContainerInterface $container ) : array {
$empty_placeholder = __( 'No webhooks found.', 'woocommerce-paypal-payments' ); $empty_placeholder = __( 'No webhooks found.', 'woocommerce-paypal-payments' );
$webhooks = array(); $webhooks = array();
@ -139,7 +139,7 @@ return array(
); );
}, },
'webhook.status.simulation' => function( $container ) : WebhookSimulation { 'webhook.status.simulation' => function( ContainerInterface $container ) : WebhookSimulation {
$webhook_endpoint = $container->get( 'api.endpoint.webhook' ); $webhook_endpoint = $container->get( 'api.endpoint.webhook' );
$webhook = $container->get( 'webhook.current' ); $webhook = $container->get( 'webhook.current' );
return new WebhookSimulation( return new WebhookSimulation(
@ -150,13 +150,13 @@ return array(
); );
}, },
'webhook.status.assets' => function( $container ) : WebhooksStatusPageAssets { 'webhook.status.assets' => function( ContainerInterface $container ) : WebhooksStatusPageAssets {
return new WebhooksStatusPageAssets( return new WebhooksStatusPageAssets(
$container->get( 'webhook.module-url' ) $container->get( 'webhook.module-url' )
); );
}, },
'webhook.endpoint.resubscribe' => static function ( $container ) : ResubscribeEndpoint { 'webhook.endpoint.resubscribe' => static function ( ContainerInterface $container ) : ResubscribeEndpoint {
$registrar = $container->get( 'webhook.registrar' ); $registrar = $container->get( 'webhook.registrar' );
$request_data = $container->get( 'button.request-data' ); $request_data = $container->get( 'button.request-data' );
@ -166,7 +166,7 @@ return array(
); );
}, },
'webhook.endpoint.simulate' => static function ( $container ) : SimulateEndpoint { 'webhook.endpoint.simulate' => static function ( ContainerInterface $container ) : SimulateEndpoint {
$simulation = $container->get( 'webhook.status.simulation' ); $simulation = $container->get( 'webhook.status.simulation' );
$request_data = $container->get( 'button.request-data' ); $request_data = $container->get( 'button.request-data' );
@ -175,7 +175,7 @@ return array(
$request_data $request_data
); );
}, },
'webhook.endpoint.simulation-state' => static function ( $container ) : SimulationStateEndpoint { 'webhook.endpoint.simulation-state' => static function ( ContainerInterface $container ) : SimulationStateEndpoint {
$simulation = $container->get( 'webhook.status.simulation' ); $simulation = $container->get( 'webhook.status.simulation' );
return new SimulationStateEndpoint( return new SimulationStateEndpoint(
@ -183,7 +183,7 @@ return array(
); );
}, },
'webhook.module-url' => static function ( $container ): string { 'webhook.module-url' => static function ( ContainerInterface $container ): string {
return plugins_url( return plugins_url(
'/modules/ppcp-webhooks/', '/modules/ppcp-webhooks/',
dirname( __FILE__, 3 ) . '/woocommerce-paypal-payments.php' dirname( __FILE__, 3 ) . '/woocommerce-paypal-payments.php'

View file

@ -50,7 +50,7 @@ class CheckoutOrderApproved implements RequestHandler {
/** /**
* The event types a handler handles. * The event types a handler handles.
* *
* @return array * @return string[]
*/ */
public function event_types(): array { public function event_types(): array {
return array( return array(

View file

@ -39,7 +39,7 @@ class CheckoutOrderCompleted implements RequestHandler {
/** /**
* The event types a handler handles. * The event types a handler handles.
* *
* @return array * @return string[]
*/ */
public function event_types(): array { public function event_types(): array {
return array( return array(

View file

@ -40,7 +40,7 @@ class PaymentCaptureCompleted implements RequestHandler {
/** /**
* The event types a handler handles. * The event types a handler handles.
* *
* @return array * @return string[]
*/ */
public function event_types(): array { public function event_types(): array {
return array( 'PAYMENT.CAPTURE.COMPLETED' ); return array( 'PAYMENT.CAPTURE.COMPLETED' );

View file

@ -39,7 +39,7 @@ class PaymentCaptureRefunded implements RequestHandler {
/** /**
* The event types a handler handles. * The event types a handler handles.
* *
* @return array * @return string[]
*/ */
public function event_types(): array { public function event_types(): array {
return array( 'PAYMENT.CAPTURE.REFUNDED' ); return array( 'PAYMENT.CAPTURE.REFUNDED' );

View file

@ -42,7 +42,7 @@ class PaymentCaptureReversed implements RequestHandler {
/** /**
* The event types a handler handles. * The event types a handler handles.
* *
* @return array * @return string[]
*/ */
public function event_types(): array { public function event_types(): array {
return array( return array(

View file

@ -17,7 +17,7 @@ interface RequestHandler {
/** /**
* The event types a handler handles. * The event types a handler handles.
* *
* @return array * @return string[]
*/ */
public function event_types(): array; public function event_types(): array;

View file

@ -248,7 +248,7 @@ class IncomingWebhookEndpoint {
/** /**
* Returns the event types, which are handled by the endpoint. * Returns the event types, which are handled by the endpoint.
* *
* @return array * @return string[]
*/ */
public function handled_event_types(): array { public function handled_event_types(): array {
$event_types = array(); $event_types = array();

View file

@ -47,14 +47,14 @@ class WebhooksStatusPageAssets {
'ppcp-webhooks-status-page-style', 'ppcp-webhooks-status-page-style',
$this->module_url . '/assets/css/status-page.css', $this->module_url . '/assets/css/status-page.css',
array(), array(),
1 '1'
); );
wp_register_script( wp_register_script(
'ppcp-webhooks-status-page', 'ppcp-webhooks-status-page',
$this->module_url . '/assets/js/status-page.js', $this->module_url . '/assets/js/status-page.js',
array(), array(),
1, '1',
true true
); );

View file

@ -78,7 +78,7 @@ class WebhookSimulation {
* *
* @throws Exception If failed to start simulation. * @throws Exception If failed to start simulation.
*/ */
public function start() { public function start(): void {
if ( ! $this->webhook ) { if ( ! $this->webhook ) {
throw new Exception( 'Webhooks not registered' ); throw new Exception( 'Webhooks not registered' );
} }

View file

@ -28,7 +28,7 @@
"docker:build-js": "docker-compose run --rm build yarn run build:dev", "docker:build-js": "docker-compose run --rm build yarn run build:dev",
"docker:composer-update": "docker-compose run --rm composer composer update && docker-compose run --rm composer composer update --lock", "docker:composer-update": "docker-compose run --rm composer composer update && docker-compose run --rm composer composer update --lock",
"docker:test": "docker-compose run --rm test vendor/bin/phpunit", "docker:test": "docker-compose run --rm test vendor/bin/phpunit",
"docker:lint": "docker-compose run --rm test vendor/bin/phpcs --parallel=8 -s", "docker:lint": "docker-compose run --rm test sh -c 'vendor/bin/phpcs --parallel=8 -s && vendor/bin/psalm --show-info=false --threads=8 --diff'",
"docker:fix-lint": "docker-compose run --rm test vendor/bin/phpcbf", "docker:fix-lint": "docker-compose run --rm test vendor/bin/phpcbf",

1012
psalm-baseline.xml Normal file

File diff suppressed because it is too large Load diff

153
psalm.xml.dist Normal file
View file

@ -0,0 +1,153 @@
<?xml version="1.0"?>
<psalm
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
xmlns:xi="http://www.w3.org/2001/XInclude"
totallyTyped="false"
useDocblockTypes="true"
usePhpDocMethodsWithoutMagicCall="false"
strictBinaryOperands="true"
rememberPropertyAssignmentsAfterCall="true"
allowPhpStormGenerics="true"
allowStringToStandInForClass="false"
memoizeMethodCallResults="false"
hoistConstants="false"
addParamDefaultToDocblockType="false"
checkForThrowsDocblock="true"
checkForThrowsInGlobalScope="false"
ignoreInternalFunctionFalseReturn="false"
ignoreInternalFunctionNullReturn="false"
throwExceptionOnError="false"
hideExternalErrors="true"
allowFileIncludes="true"
errorBaseline="psalm-baseline.xml"
>
<projectFiles>
<directory name="src"/>
<directory name="modules" />
</projectFiles>
<stubs>
<file name="vendor/php-stubs/wordpress-stubs/wordpress-stubs.php"/>
<file name="vendor/php-stubs/woocommerce-stubs/woocommerce-stubs.php"/>
</stubs>
<issueHandlers>
<ConflictingReferenceConstraint errorLevel="error"/>
<ContinueOutsideLoop errorLevel="error"/>
<DuplicateArrayKey errorLevel="error"/>
<DuplicateClass errorLevel="error"/>
<DuplicateFunction errorLevel="error"/>
<DuplicateMethod errorLevel="error"/>
<DuplicateParam errorLevel="error"/>
<EmptyArrayAccess errorLevel="error"/>
<FalsableReturnStatement errorLevel="error"/>
<FalseOperand errorLevel="error"/>
<ForbiddenCode errorLevel="error"/>
<ForbiddenEcho errorLevel="error"/>
<InaccessibleClassConstant errorLevel="error"/>
<InaccessibleMethod errorLevel="error"/>
<InterfaceInstantiation errorLevel="error"/>
<InaccessibleProperty errorLevel="error"/>
<InternalClass errorLevel="error"/>
<InternalMethod errorLevel="error"/>
<InternalProperty errorLevel="error"/>
<InvalidArgument errorLevel="error"/>
<InvalidArrayAccess errorLevel="error"/>
<InvalidArrayAssignment errorLevel="error"/>
<InvalidArrayOffset errorLevel="error"/>
<InvalidCast errorLevel="error"/>
<InvalidCatch errorLevel="error"/>
<InvalidClass errorLevel="error"/>
<InvalidClone errorLevel="error"/>
<InvalidFalsableReturnType errorLevel="error"/>
<InvalidThrow errorLevel="error"/>
<InvalidToString errorLevel="error"/>
<LoopInvalidation errorLevel="error"/>
<InvalidNullableReturnType errorLevel="error"/>
<LessSpecificReturnType errorLevel="error"/>
<InvalidGlobal errorLevel="error"/>
<InvalidIterator errorLevel="error"/>
<InvalidMethodCall errorLevel="error"/>
<InvalidFunctionCall errorLevel="error"/>
<ImplicitToStringCast errorLevel="error"/>
<ImplementedReturnTypeMismatch errorLevel="error"/>
<InvalidParamDefault errorLevel="error"/>
<InvalidPassByReference errorLevel="error"/>
<InvalidPropertyAssignment errorLevel="error"/>
<InvalidPropertyAssignmentValue errorLevel="error"/>
<InvalidPropertyFetch errorLevel="error"/>
<InvalidReturnStatement errorLevel="error"/>
<InvalidReturnType errorLevel="error"/>
<InvalidScalarArgument errorLevel="error"/>
<InvalidScope errorLevel="error"/>
<InvalidStaticInvocation errorLevel="error"/>
<MissingConstructor errorLevel="error"/>
<MissingDependency errorLevel="error"/>
<MissingFile errorLevel="error"/>
<MixedArgument errorLevel="error"/>
<MoreSpecificImplementedParamType errorLevel="error"/>
<MoreSpecificReturnType errorLevel="error"/>
<NoValue errorLevel="error"/>
<NoInterfaceProperties errorLevel="error"/>
<NonStaticSelfCall errorLevel="error"/>
<NullableReturnStatement errorLevel="error"/>
<NullArgument errorLevel="error"/>
<NullArrayAccess errorLevel="error"/>
<NullArrayOffset errorLevel="error"/>
<NullFunctionCall errorLevel="error"/>
<NullIterator errorLevel="error"/>
<NullOperand errorLevel="error"/>
<NullPropertyAssignment errorLevel="error"/>
<NullPropertyFetch errorLevel="error"/>
<NullReference errorLevel="error"/>
<OverriddenMethodAccess errorLevel="error"/>
<OverriddenPropertyAccess errorLevel="error"/>
<ParadoxicalCondition errorLevel="error"/>
<ParentNotFound errorLevel="error"/>
<LessSpecificImplementedReturnType errorLevel="error"/>
<MissingParamType errorLevel="error"/>
<MissingClosureParamType errorLevel="error"/>
<MissingClosureReturnType errorLevel="error"/>
<MissingPropertyType errorLevel="error"/>
<UndefinedConstant errorLevel="error"/>
<AssignmentToVoid errorLevel="info"/>
<DeprecatedClass errorLevel="info"/>
<DeprecatedConstant errorLevel="info"/>
<DeprecatedTrait errorLevel="info"/>
<DocblockTypeContradiction errorLevel="info"/>
<InvalidDocblock errorLevel="info"/>
<InvalidDocblockParamName errorLevel="info"/>
<InvalidTemplateParam errorLevel="info"/>
<DeprecatedInterface errorLevel="info"/>
<DeprecatedMethod errorLevel="info"/>
<DeprecatedProperty errorLevel="info"/>
<MethodSignatureMustOmitReturnType errorLevel="info"/>
<MismatchingDocblockParamType errorLevel="info"/>
<MismatchingDocblockReturnType errorLevel="info"/>
<MissingDocblockType errorLevel="info"/>
<MissingParamType errorLevel="info"/>
<MissingTemplateParam errorLevel="info"/>
<MissingThrowsDocblock errorLevel="info"/>
<MixedArgumentTypeCoercion errorLevel="info"/>
<MixedArrayAccess errorLevel="info"/>
<MixedArrayAssignment errorLevel="info"/>
<MixedArrayOffset errorLevel="info"/>
<MixedArrayTypeCoercion errorLevel="info"/>
<MixedAssignment errorLevel="info"/>
<MixedFunctionCall errorLevel="info"/>
<MixedInferredReturnType errorLevel="info"/>
<MixedMethodCall errorLevel="info"/>
<MixedOperand errorLevel="info"/>
<MixedPropertyAssignment errorLevel="info"/>
<MixedPropertyFetch errorLevel="info"/>
<MixedPropertyTypeCoercion errorLevel="info"/>
<MixedReturnStatement errorLevel="info"/>
<MixedReturnTypeCoercion errorLevel="info"/>
<MixedStringOffsetAssignment errorLevel="info"/>
<ParamNameMismatch errorLevel="info"/>
</issueHandlers>
</psalm>