Plugin Directory

Changeset 3751048


Ignore:
Timestamp:
10/16/2026 07:51:27 PM (4 weeks ago)
Author:
digitalkind
Message:

Airworthy 1.0.1

Location:
airworthy
Files:
3 added
22 edited
1 copied

Legend:

Unmodified
Added
Removed
  • airworthy/tags/1.0.1/airworthy.php

    r3722113 r3751048  
    44 * Plugin URI:        https://airworthywp.com
    55 * Description:       Before you upgrade PHP, see which plugins and themes are ready, which need fixing, and which look abandoned.
    6  * Version:           1.0.0
     6 * Version:           1.0.1
    77 * Requires at least: 6.9
    88 * Requires PHP:      7.2
    … …  
    2525}
    2626
    27 define( 'AIRWORTHY_VERSION', '1.0.0' );
     27define( 'AIRWORTHY_VERSION', '1.0.1' );
    2828define( 'AIRWORTHY_FILE', __FILE__ );
    2929define( 'AIRWORTHY_DIR', plugin_dir_path( __FILE__ ) );
  • airworthy/tags/1.0.1/assets/admin.css

    r3722113 r3751048  
    12001200        box-shadow: 0 1px 2px rgba(23, 71, 166, 0.3);
    12011201}
     1202
     1203/* "Did Airworthy help?" below a finished scan's results. */
     1204
     1205.airworthy-wrap .airworthy-review {
     1206        border-left: 4px solid #2f74e8;
     1207}
     1208
     1209.airworthy-review p {
     1210        max-width: 46rem;
     1211}
     1212
     1213.airworthy-review-actions {
     1214        display: flex;
     1215        flex-wrap: wrap;
     1216        gap: 16px;
     1217        align-items: center;
     1218}
     1219
     1220.airworthy-head-actions {
     1221        flex-wrap: wrap;
     1222}
  • airworthy/tags/1.0.1/assets/admin.js

    r3722113 r3751048  
    14431443                                                { class: 'airworthy-head-actions' },
    14441444                                                el( 'a', { class: 'button', href: scan.export_url }, __( 'Export CSV', 'airworthy' ) ),
     1445                                                el(
     1446                                                        'button',
     1447                                                        { type: 'button', class: 'button airworthy-copy-summary', onclick: function ( event ) {
     1448                                                                copySummary( scan, components, event.currentTarget );
     1449                                                        } },
     1450                                                        __( 'Copy summary', 'airworthy' )
     1451                                                ),
    14451452                                                ( config.resultsActions || [] ).map(
    14461453                                                        function ( a ) {
    … …  
    15351542                                        }
    15361543                                ) : el( 'tbody', null, el( 'tr', null, el( 'td', { colspan: 5 }, __( 'No plugins or themes were checked in this scan.', 'airworthy' ) ) ) )
    1537                         )
     1544                        ),
     1545                        'complete' === scan.status && config.review ? reviewCard() : null
    15381546                );
    15391547                show( 'results' );
    … …  
    15491557                }
    15501558                watchWporg( scan );
     1559        }
     1560
     1561        /**
     1562         * A plain-text summary of the results, for an email or support ticket to a host or
     1563         * developer: the overall answer, then each plugin and theme grouped by what to do next.
     1564         */
     1565        function summaryText( scan, components ) {
     1566                var counts = {};
     1567                components.forEach(
     1568                        function ( c ) {
     1569                                counts[ c.verdict ] = ( counts[ c.verdict ] || 0 ) + 1;
     1570                        }
     1571                );
     1572                var needs   = counts.blocker || 0;
     1573                var overall = 'complete' !== scan.status ?
     1574                        __( 'The scan was stopped before it finished, so these results are incomplete.', 'airworthy' ) :
     1575                        ( needs ?
     1576                                /* translators: 1: number of plugins/themes, 2: PHP version. */
     1577                                sprintf( _n( '%1$d plugin or theme needs attention before the upgrade to PHP %2$s.', '%1$d plugins or themes need attention before the upgrade to PHP %2$s.', needs, 'airworthy' ), needs, scan.target_php ) :
     1578                                ( counts.unknown ?
     1579                                        /* translators: %s: PHP version. */
     1580                                        sprintf( __( 'Nothing found that would break on PHP %s, but some files could not be checked.', 'airworthy' ), scan.target_php ) :
     1581                                        /* translators: %s: PHP version. */
     1582                                        sprintf( __( 'Nothing found that would break on PHP %s.', 'airworthy' ), scan.target_php ) ) );
     1583
     1584                var lines = [
     1585                        /* translators: %s: PHP version. */
     1586                        sprintf( __( 'Airworthy check for PHP %s', 'airworthy' ), scan.target_php ),
     1587                        [
     1588                                /* translators: %s: date and time. */
     1589                                scan.finished_at ? sprintf( __( 'Checked %s', 'airworthy' ), formatDateTime( scan.finished_at ) ) : '',
     1590                                /* translators: %s: PHP version. */
     1591                                sprintf( __( 'server runs PHP %s', 'airworthy' ), scan.host_php ),
     1592                        ].filter( Boolean ).join( ' · ' ),
     1593                        '',
     1594                        overall,
     1595                ];
     1596
     1597                resultGroups( scan, components ).forEach(
     1598                        function ( g ) {
     1599                                lines.push( '', g.title + ':' );
     1600                                if ( 'good' === g.key ) {
     1601                                        var names = g.items.map(
     1602                                                function ( c ) {
     1603                                                        return c.name;
     1604                                                }
     1605                                        );
     1606                                        lines.push( names.join( ', ' ) );
     1607                                        return;
     1608                                }
     1609                                g.items.forEach(
     1610                                        function ( c ) {
     1611                                                var notes = [];
     1612                                                if ( c.verdict && VERDICTS[ c.verdict ] ) {
     1613                                                        notes.push( VERDICTS[ c.verdict ].label );
     1614                                                }
     1615                                                if ( c.update ) {
     1616                                                        /* translators: %s: version number. */
     1617                                                        notes.push( sprintf( __( 'update available: %s', 'airworthy' ), c.update.version ) );
     1618                                                }
     1619                                                if ( c.wporg && 'closed' === c.wporg.status ) {
     1620                                                        notes.push( __( 'removed from WordPress.org', 'airworthy' ) );
     1621                                                } else if ( c.wporg && c.wporg.abandoned ) {
     1622                                                        notes.push( __( 'looks abandoned', 'airworthy' ) );
     1623                                                }
     1624                                                if ( c.wporg && c.wporg.requires_php_blocker ) {
     1625                                                        /* translators: %s: PHP version. */
     1626                                                        notes.push( sprintf( __( 'requires PHP %s', 'airworthy' ), c.wporg.requires_php ) );
     1627                                                }
     1628                                                lines.push( '- ' + c.name + ( c.version ? ' ' + c.version : '' ) + ( notes.length ? ' (' + notes.join( ', ' ) + ')' : '' ) );
     1629                                        }
     1630                                );
     1631                        }
     1632                );
     1633
     1634                lines.push(
     1635                        '',
     1636                        __( 'Airworthy reads the code without running it, so test the new PHP version on a staging copy before switching the live site.', 'airworthy' ),
     1637                        /* translators: %s: link to Airworthy on WordPress.org. */
     1638                        sprintf( __( 'Checked with Airworthy (free): %s', 'airworthy' ), config.pluginUrl || 'https://wordpress.org/plugins/airworthy/' )
     1639                );
     1640                return lines.join( '\n' );
     1641        }
     1642
     1643        /**
     1644         * Copies the summary, and says so on the button for a moment. Falls back to a hidden text
     1645         * box where the clipboard API isn't available (admin screens served over plain http).
     1646         */
     1647        function copySummary( scan, components, button ) {
     1648                var text     = summaryText( scan, components );
     1649                var done     = function () {
     1650                        var label          = button.textContent;
     1651                        button.textContent = __( 'Copied', 'airworthy' );
     1652                        announce( __( 'Summary copied. Paste it into an email or support ticket.', 'airworthy' ) );
     1653                        setTimeout(
     1654                                function () {
     1655                                        button.textContent = label;
     1656                                },
     1657                                2500
     1658                        );
     1659                };
     1660                var fallback = function () {
     1661                        var box   = el( 'textarea', { class: 'screen-reader-text', readonly: 'readonly' } );
     1662                        box.value = text;
     1663                        document.body.appendChild( box );
     1664                        box.select();
     1665                        var ok = false;
     1666                        try {
     1667                                ok = document.execCommand( 'copy' );
     1668                        } catch ( e ) {
     1669                                ok = false;
     1670                        }
     1671                        document.body.removeChild( box );
     1672                        if ( ok ) {
     1673                                done();
     1674                        } else {
     1675                                window.prompt( __( 'Copy the summary:', 'airworthy' ), text );
     1676                        }
     1677                };
     1678                if ( navigator.clipboard && window.isSecureContext ) {
     1679                        navigator.clipboard.writeText( text ).then( done, fallback );
     1680                } else {
     1681                        fallback();
     1682                }
     1683        }
     1684
     1685        /**
     1686         * "Did Airworthy help?" below the results of a finished scan. Asked once per user: Leave a
     1687         * review and Don't ask again end it, Maybe later asks again in 30 days.
     1688         */
     1689        function reviewCard() {
     1690                var card   = null;
     1691                var answer = function ( choice ) {
     1692                        config.review = null; // Not again on this page.
     1693                        if ( card && card.parentNode ) {
     1694                                card.parentNode.removeChild( card );
     1695                        }
     1696                        apiFetch( { path: REST + '/review', method: 'POST', data: { choice: choice } } ).catch( function () {} );
     1697                        if ( 'done' !== choice ) {
     1698                                announce( __( 'Thanks. Airworthy won\'t ask again for now.', 'airworthy' ) );
     1699                        }
     1700                };
     1701                card       = el(
     1702                        'div',
     1703                        { class: 'airworthy-card airworthy-review' },
     1704                        el( 'h3', null, __( 'Did Airworthy help?', 'airworthy' ) ),
     1705                        el( 'p', null, __( 'Airworthy is free. A short review on WordPress.org helps other site owners find it before their own PHP upgrade, and takes about a minute.', 'airworthy' ) ),
     1706                        el(
     1707                                'p',
     1708                                { class: 'airworthy-review-actions' },
     1709                                el(
     1710                                        'a',
     1711                                        { class: 'button button-primary', href: config.review.url, target: '_blank', rel: 'noopener', onclick: function () {
     1712                                                answer( 'done' );
     1713                                        } },
     1714                                        __( 'Leave a review', 'airworthy' ),
     1715                                        el( 'span', { class: 'screen-reader-text' }, __( '(opens in a new tab)', 'airworthy' ) )
     1716                                ),
     1717                                el(
     1718                                        'button',
     1719                                        { type: 'button', class: 'button-link', onclick: function () {
     1720                                                answer( 'later' );
     1721                                        } },
     1722                                        __( 'Maybe later', 'airworthy' )
     1723                                ),
     1724                                el(
     1725                                        'button',
     1726                                        { type: 'button', class: 'button-link', onclick: function () {
     1727                                                answer( 'never' );
     1728                                        } },
     1729                                        __( 'Don\'t ask again', 'airworthy' )
     1730                                )
     1731                        )
     1732                );
     1733                return card;
    15511734        }
    15521735
  • airworthy/tags/1.0.1/readme.txt

    r3739681 r3751048  
    55Tested up to: 7.1
    66Requires PHP: 7.2
    7 Stable tag: 1.0.0
     7Stable tag: 1.0.1
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    2222
    2323* **A verdict for every plugin and theme.** Blocker, Unknown, Suppressed, Guarded, Warnings or Ready, each with one plain sentence explaining what it means for you.
    24 * **Fewer false alarms.** Many plugins carry old code that only runs on old PHP versions, behind a version check. Airworthy recognises those checks and marks that code as guarded instead of broken. In our test of the 30 most popular plugins, this cut the plugins flagged as broken from 4 to 2, and in both the flagged code really would fail on PHP 8.
     24* **Fewer false alarms.** Many plugins carry old code that only runs on old PHP versions, behind a version check. Airworthy recognises those checks and marks that code as guarded instead of broken. In our test of the 30 most popular plugins, this cut the plugins flagged as broken from 4 to 2, and both of those contain code that really would fail on PHP 8.
    2525* **Maintenance signals from WordPress.org (if you allow it).** Plugins that were closed (removed from the directory), not updated in two years, not tested with recent WordPress versions, or that need a newer PHP version than you picked are called out.
    2626* **Know what to do next.** Results are grouped into fix before you upgrade, keep an eye on, and all good. Plugins with an update waiting say so, with a one-click update, and Airworthy checks them again once they're updated.
    2727* **Know how long you have.** Airworthy shows when your server's PHP version stops getting security fixes, so you can plan the upgrade before it's urgent.
    28 * **The details when you want them.** Every finding shows the file, the line and what changed in PHP. Filter by verdict, rescan one plugin after an update, or download everything as a CSV file for your developer or host.
     28* **The details when you want them.** Every finding shows the file, the line and what changed in PHP. Filter by verdict, rescan one plugin after an update, copy a plain-text summary to paste into an email or support ticket, or download everything as a CSV file for your developer or host.
    2929* **Sensible default.** Airworthy recommends the oldest PHP version that still gets security fixes: the smallest upgrade that keeps your site protected. It shows every version's support dates.
    3030* **Safe on any host.** Scans run in the background in short batches, so they never time out, and they watch memory use. You can leave the page while a scan runs. Nothing is changed on your site.
    … …  
    3232* **In Site Health too.** Tools > Site Health shows whether your plugins and themes are ready for the next PHP version, with a link to the full results.
    3333* **Multisite ready.** On a network, Airworthy is activated network-wide and lives under Network Admin > Settings.
     34
     35= For freelancers and agencies =
     36
     37Hosts are moving sites off old PHP versions, and every client asks the same question: will my site break? Install Airworthy on each client site before the host's deadline (it's free, on as many sites as you like), and you have an answer per plugin in minutes. Copy summary gives you a plain-text list to paste into the client email or the host's support ticket, the CSV has every finding for your developer, and the Site Health check keeps showing whether the site is ready for the next PHP version. For many sites at once, use WP-CLI.
    3438
    3539= WP-CLI =
    … …  
    136140That menu comes from Action Scheduler, the background-job library Airworthy uses (WooCommerce uses the same one). It's harmless, and lists Airworthy's jobs under the "airworthy" group.
    137141
     142= Can I use Airworthy on client sites? =
     143
     144Yes. Airworthy is free and GPL-licensed, with no limit on sites and no account. Agencies often run it from WP-CLI (`wp airworthy scan --target=8.4 --fail-on=blocker`) across all their sites, and use Copy summary or the CSV export for each client.
     145
    138146= How do I report a security problem? =
    139147
    … …  
    1481565. Settings: skip inactive plugins, never check chosen plugins or themes, and pick a scan speed that suits your hosting. Changes save as you make them.
    1491576. A PHP upgrade check in Tools > Site Health, next to WordPress's own checks.
     1587. The same check from WP-CLI, for agencies looking after many sites.
    150159
    151160== Changelog ==
     161
     162= 1.0.1 =
     163* New: Copy summary, next to Export CSV on the results. Copies a plain-text summary (the overall answer, then each plugin and theme grouped by what to do next, with updates waiting and closed plugins) to paste into an email or support ticket for your host or developer.
     164* New: after a finished scan, the results ask once whether you'd leave a review on WordPress.org. Maybe later asks again in 30 days; Don't ask again means never. It only appears on Airworthy's own screen, below the results.
     165* PHP support dates checked against php.net on 16 October 2026: PHP 8.2 gets security fixes until 31 December 2026.
     166* WP-CLI: the note about problems that already apply on your current PHP version now says how to list them (`wp airworthy results --fields=name,verdict,existing`); it pointed to a column the scan table doesn't show.
    152167
    153168= 1.0.0 =
    … …  
    167182== Upgrade Notice ==
    168183
     184= 1.0.1 =
     185Adds Copy summary on the results, for sending to your host or developer.
     186
    169187= 1.0.0 =
    170188First release.
  • airworthy/tags/1.0.1/sbom.cdx.json

    r3722113 r3751048  
    44    "version": 1,
    55    "metadata": {
    6         "timestamp": "2026-09-30T21:58:36Z",
     6        "timestamp": "2026-10-16T19:45:22Z",
    77        "component": {
    88            "type": "application",
    9             "bom-ref": "pkg:wordpress-plugin/airworthy@1.0.0",
     9            "bom-ref": "pkg:wordpress-plugin/airworthy@1.0.1",
    1010            "name": "airworthy",
    11             "version": "1.0.0",
     11            "version": "1.0.1",
    1212            "description": "Airworthy – PHP Compatibility & Upgrade Checker (WordPress plugin)",
    1313            "licenses": [
    … …  
    209209    "dependencies": [
    210210        {
    211             "ref": "pkg:wordpress-plugin/airworthy@1.0.0",
     211            "ref": "pkg:wordpress-plugin/airworthy@1.0.1",
    212212            "dependsOn": [
    213213                "pkg:composer/phpcompatibility/php-compatibility@10.0.0-alpha2",
  • airworthy/tags/1.0.1/src/Admin/Page.php

    r3722113 r3751048  
    8282                                        'cronDisabled'   => defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON,
    8383                                        'resultsActions' => self::results_actions(),
     84                                        'review'         => Review::config(),
     85                                        'pluginUrl'      => 'https://wordpress.org/plugins/airworthy/',
    8486                                )
    8587                        ) . ';',
  • airworthy/tags/1.0.1/src/Cli/Command.php

    r3722113 r3751048  
    529529                        $existing = array_sum( wp_list_pluck( $this->components( $scan_id ), 'existing' ) );
    530530                        if ( $existing && ! empty( $scan->from_php ) ) {
    531                                 WP_CLI::log( sprintf( '%1$d problems already apply on PHP %2$s, so they are not caused by this upgrade (see the "existing" column).', $existing, $scan->from_php ) );
     531                                WP_CLI::log(
     532                                        sprintf(
     533                                                1 === $existing ?
     534                                                '%1$d problem already applies on PHP %2$s, so it is not caused by this upgrade. To see where: wp airworthy results --fields=name,verdict,existing' :
     535                                                '%1$d problems already apply on PHP %2$s, so they are not caused by this upgrade. To see where: wp airworthy results --fields=name,verdict,existing',
     536                                                $existing,
     537                                                $scan->from_php
     538                                        )
     539                                );
    532540                        }
    533541                        if ( in_array( $scan->wporg_status, array( 'offline', 'partial' ), true ) ) {
  • airworthy/tags/1.0.1/src/Installer.php

    r3722113 r3751048  
    199199                        delete_site_option( $option );
    200200                }
     201                \Airworthy\Admin\Review::forget_all(); // Each user's answer to the review request.
    201202
    202203                // Cached WordPress.org lookups. They're site transients, which live in the options table
  • airworthy/tags/1.0.1/src/Rest/Controller.php

    r3722113 r3751048  
    217217                                'permission_callback' => $can,
    218218                                'args'                => array( 'id' => $id ),
     219                        )
     220                );
     221                register_rest_route(
     222                        $ns,
     223                        '/review',
     224                        array(
     225                                'methods'             => 'POST',
     226                                'callback'            => array( \Airworthy\Admin\Review::class, 'rest_answer' ),
     227                                'permission_callback' => $can,
     228                                'args'                => array(
     229                                        'choice' => array(
     230                                                'required'    => true,
     231                                                'type'        => 'string',
     232                                                'enum'        => \Airworthy\Admin\Review::CHOICES,
     233                                                'description' => __( 'The user\'s answer to the review request: done, later or never.', 'airworthy' ),
     234                                        ),
     235                                ),
    219236                        )
    220237                );
  • airworthy/tags/1.0.1/src/Targets.php

    r3722113 r3751048  
    3838
    3939        /** When SECURITY_UNTIL was last checked against php.net. */
    40         const TABLE_CHECKED = '2026-09-29';
     40        const TABLE_CHECKED = '2026-10-16';
    4141
    4242        /**
  • airworthy/tags/1.0.1/vendor/composer/installed.php

    r3722113 r3751048  
    33namespace Airworthy\Vendor;
    44
    5 return array('root' => array('name' => 'digitalkind/airworthy', 'pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '8ed4539c1fdedf95361a42ed753e4a4897ecf320', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \false), 'versions' => array('dealerdirect/phpcodesniffer-composer-installer' => array('pretty_version' => 'v1.2.1', 'version' => '1.2.1.0', 'reference' => '963f0c67bffde0eac41b56be71ac0e8ba132f0bd', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../dealerdirect/phpcodesniffer-composer-installer', 'aliases' => array(), 'dev_requirement' => \false), 'digitalkind/airworthy' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '8ed4539c1fdedf95361a42ed753e4a4897ecf320', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/php-compatibility' => array('pretty_version' => '10.0.0-alpha2', 'version' => '10.0.0.0-alpha2', 'reference' => 'e0f0e5a3dc819a4a0f8d679a0f2453d941976e18', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/php-compatibility', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/phpcompatibility-paragonie' => array('pretty_version' => '2.0.0-alpha2', 'version' => '2.0.0.0-alpha2', 'reference' => '7a979711c87d8202b52f56c56bd719d09d8ed7f5', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/phpcompatibility-paragonie', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/phpcompatibility-wp' => array('pretty_version' => '3.0.0-alpha2', 'version' => '3.0.0.0-alpha2', 'reference' => 'bd53f24e7528422ac51d64dc8d53e8d4c4a877b3', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/phpcompatibility-wp', 'aliases' => array(), 'dev_requirement' => \false), 'phpcsstandards/phpcsutils' => array('pretty_version' => '1.2.3', 'version' => '1.2.3.0', 'reference' => '5f35d9408c54d7b529501f3c688b6eae562aea1f', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcsstandards/phpcsutils', 'aliases' => array(), 'dev_requirement' => \false), 'squizlabs/php_codesniffer' => array('pretty_version' => '4.0.4', 'version' => '4.0.4.0', 'reference' => 'bbdc3d0532623e21838b7041a4364383a8126f96', 'type' => 'library', 'install_path' => __DIR__ . '/../squizlabs/php_codesniffer', 'aliases' => array(), 'dev_requirement' => \false), 'wimg/php-compatibility' => array('dev_requirement' => \false, 'replaced' => array(0 => '*')), 'woocommerce/action-scheduler' => array('pretty_version' => '4.2.0', 'version' => '4.2.0.0', 'reference' => '9e2c6b02e89652bade4445ea2ca5fb12e0fa7242', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../woocommerce/action-scheduler', 'aliases' => array(), 'dev_requirement' => \false)));
     5return array('root' => array('name' => 'digitalkind/airworthy', 'pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '9c9a53d3656967dc5abc254b265e07368204d493', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \false), 'versions' => array('dealerdirect/phpcodesniffer-composer-installer' => array('pretty_version' => 'v1.2.1', 'version' => '1.2.1.0', 'reference' => '963f0c67bffde0eac41b56be71ac0e8ba132f0bd', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../dealerdirect/phpcodesniffer-composer-installer', 'aliases' => array(), 'dev_requirement' => \false), 'digitalkind/airworthy' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '9c9a53d3656967dc5abc254b265e07368204d493', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/php-compatibility' => array('pretty_version' => '10.0.0-alpha2', 'version' => '10.0.0.0-alpha2', 'reference' => 'e0f0e5a3dc819a4a0f8d679a0f2453d941976e18', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/php-compatibility', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/phpcompatibility-paragonie' => array('pretty_version' => '2.0.0-alpha2', 'version' => '2.0.0.0-alpha2', 'reference' => '7a979711c87d8202b52f56c56bd719d09d8ed7f5', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/phpcompatibility-paragonie', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/phpcompatibility-wp' => array('pretty_version' => '3.0.0-alpha2', 'version' => '3.0.0.0-alpha2', 'reference' => 'bd53f24e7528422ac51d64dc8d53e8d4c4a877b3', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/phpcompatibility-wp', 'aliases' => array(), 'dev_requirement' => \false), 'phpcsstandards/phpcsutils' => array('pretty_version' => '1.2.3', 'version' => '1.2.3.0', 'reference' => '5f35d9408c54d7b529501f3c688b6eae562aea1f', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcsstandards/phpcsutils', 'aliases' => array(), 'dev_requirement' => \false), 'squizlabs/php_codesniffer' => array('pretty_version' => '4.0.4', 'version' => '4.0.4.0', 'reference' => 'bbdc3d0532623e21838b7041a4364383a8126f96', 'type' => 'library', 'install_path' => __DIR__ . '/../squizlabs/php_codesniffer', 'aliases' => array(), 'dev_requirement' => \false), 'wimg/php-compatibility' => array('dev_requirement' => \false, 'replaced' => array(0 => '*')), 'woocommerce/action-scheduler' => array('pretty_version' => '4.2.0', 'version' => '4.2.0.0', 'reference' => '9e2c6b02e89652bade4445ea2ca5fb12e0fa7242', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../woocommerce/action-scheduler', 'aliases' => array(), 'dev_requirement' => \false)));
  • airworthy/trunk/airworthy.php

    r3722113 r3751048  
    44 * Plugin URI:        https://airworthywp.com
    55 * Description:       Before you upgrade PHP, see which plugins and themes are ready, which need fixing, and which look abandoned.
    6  * Version:           1.0.0
     6 * Version:           1.0.1
    77 * Requires at least: 6.9
    88 * Requires PHP:      7.2
    … …  
    2525}
    2626
    27 define( 'AIRWORTHY_VERSION', '1.0.0' );
     27define( 'AIRWORTHY_VERSION', '1.0.1' );
    2828define( 'AIRWORTHY_FILE', __FILE__ );
    2929define( 'AIRWORTHY_DIR', plugin_dir_path( __FILE__ ) );
  • airworthy/trunk/assets/admin.css

    r3722113 r3751048  
    12001200        box-shadow: 0 1px 2px rgba(23, 71, 166, 0.3);
    12011201}
     1202
     1203/* "Did Airworthy help?" below a finished scan's results. */
     1204
     1205.airworthy-wrap .airworthy-review {
     1206        border-left: 4px solid #2f74e8;
     1207}
     1208
     1209.airworthy-review p {
     1210        max-width: 46rem;
     1211}
     1212
     1213.airworthy-review-actions {
     1214        display: flex;
     1215        flex-wrap: wrap;
     1216        gap: 16px;
     1217        align-items: center;
     1218}
     1219
     1220.airworthy-head-actions {
     1221        flex-wrap: wrap;
     1222}
  • airworthy/trunk/assets/admin.js

    r3722113 r3751048  
    14431443                                                { class: 'airworthy-head-actions' },
    14441444                                                el( 'a', { class: 'button', href: scan.export_url }, __( 'Export CSV', 'airworthy' ) ),
     1445                                                el(
     1446                                                        'button',
     1447                                                        { type: 'button', class: 'button airworthy-copy-summary', onclick: function ( event ) {
     1448                                                                copySummary( scan, components, event.currentTarget );
     1449                                                        } },
     1450                                                        __( 'Copy summary', 'airworthy' )
     1451                                                ),
    14451452                                                ( config.resultsActions || [] ).map(
    14461453                                                        function ( a ) {
    … …  
    15351542                                        }
    15361543                                ) : el( 'tbody', null, el( 'tr', null, el( 'td', { colspan: 5 }, __( 'No plugins or themes were checked in this scan.', 'airworthy' ) ) ) )
    1537                         )
     1544                        ),
     1545                        'complete' === scan.status && config.review ? reviewCard() : null
    15381546                );
    15391547                show( 'results' );
    … …  
    15491557                }
    15501558                watchWporg( scan );
     1559        }
     1560
     1561        /**
     1562         * A plain-text summary of the results, for an email or support ticket to a host or
     1563         * developer: the overall answer, then each plugin and theme grouped by what to do next.
     1564         */
     1565        function summaryText( scan, components ) {
     1566                var counts = {};
     1567                components.forEach(
     1568                        function ( c ) {
     1569                                counts[ c.verdict ] = ( counts[ c.verdict ] || 0 ) + 1;
     1570                        }
     1571                );
     1572                var needs   = counts.blocker || 0;
     1573                var overall = 'complete' !== scan.status ?
     1574                        __( 'The scan was stopped before it finished, so these results are incomplete.', 'airworthy' ) :
     1575                        ( needs ?
     1576                                /* translators: 1: number of plugins/themes, 2: PHP version. */
     1577                                sprintf( _n( '%1$d plugin or theme needs attention before the upgrade to PHP %2$s.', '%1$d plugins or themes need attention before the upgrade to PHP %2$s.', needs, 'airworthy' ), needs, scan.target_php ) :
     1578                                ( counts.unknown ?
     1579                                        /* translators: %s: PHP version. */
     1580                                        sprintf( __( 'Nothing found that would break on PHP %s, but some files could not be checked.', 'airworthy' ), scan.target_php ) :
     1581                                        /* translators: %s: PHP version. */
     1582                                        sprintf( __( 'Nothing found that would break on PHP %s.', 'airworthy' ), scan.target_php ) ) );
     1583
     1584                var lines = [
     1585                        /* translators: %s: PHP version. */
     1586                        sprintf( __( 'Airworthy check for PHP %s', 'airworthy' ), scan.target_php ),
     1587                        [
     1588                                /* translators: %s: date and time. */
     1589                                scan.finished_at ? sprintf( __( 'Checked %s', 'airworthy' ), formatDateTime( scan.finished_at ) ) : '',
     1590                                /* translators: %s: PHP version. */
     1591                                sprintf( __( 'server runs PHP %s', 'airworthy' ), scan.host_php ),
     1592                        ].filter( Boolean ).join( ' · ' ),
     1593                        '',
     1594                        overall,
     1595                ];
     1596
     1597                resultGroups( scan, components ).forEach(
     1598                        function ( g ) {
     1599                                lines.push( '', g.title + ':' );
     1600                                if ( 'good' === g.key ) {
     1601                                        var names = g.items.map(
     1602                                                function ( c ) {
     1603                                                        return c.name;
     1604                                                }
     1605                                        );
     1606                                        lines.push( names.join( ', ' ) );
     1607                                        return;
     1608                                }
     1609                                g.items.forEach(
     1610                                        function ( c ) {
     1611                                                var notes = [];
     1612                                                if ( c.verdict && VERDICTS[ c.verdict ] ) {
     1613                                                        notes.push( VERDICTS[ c.verdict ].label );
     1614                                                }
     1615                                                if ( c.update ) {
     1616                                                        /* translators: %s: version number. */
     1617                                                        notes.push( sprintf( __( 'update available: %s', 'airworthy' ), c.update.version ) );
     1618                                                }
     1619                                                if ( c.wporg && 'closed' === c.wporg.status ) {
     1620                                                        notes.push( __( 'removed from WordPress.org', 'airworthy' ) );
     1621                                                } else if ( c.wporg && c.wporg.abandoned ) {
     1622                                                        notes.push( __( 'looks abandoned', 'airworthy' ) );
     1623                                                }
     1624                                                if ( c.wporg && c.wporg.requires_php_blocker ) {
     1625                                                        /* translators: %s: PHP version. */
     1626                                                        notes.push( sprintf( __( 'requires PHP %s', 'airworthy' ), c.wporg.requires_php ) );
     1627                                                }
     1628                                                lines.push( '- ' + c.name + ( c.version ? ' ' + c.version : '' ) + ( notes.length ? ' (' + notes.join( ', ' ) + ')' : '' ) );
     1629                                        }
     1630                                );
     1631                        }
     1632                );
     1633
     1634                lines.push(
     1635                        '',
     1636                        __( 'Airworthy reads the code without running it, so test the new PHP version on a staging copy before switching the live site.', 'airworthy' ),
     1637                        /* translators: %s: link to Airworthy on WordPress.org. */
     1638                        sprintf( __( 'Checked with Airworthy (free): %s', 'airworthy' ), config.pluginUrl || 'https://wordpress.org/plugins/airworthy/' )
     1639                );
     1640                return lines.join( '\n' );
     1641        }
     1642
     1643        /**
     1644         * Copies the summary, and says so on the button for a moment. Falls back to a hidden text
     1645         * box where the clipboard API isn't available (admin screens served over plain http).
     1646         */
     1647        function copySummary( scan, components, button ) {
     1648                var text     = summaryText( scan, components );
     1649                var done     = function () {
     1650                        var label          = button.textContent;
     1651                        button.textContent = __( 'Copied', 'airworthy' );
     1652                        announce( __( 'Summary copied. Paste it into an email or support ticket.', 'airworthy' ) );
     1653                        setTimeout(
     1654                                function () {
     1655                                        button.textContent = label;
     1656                                },
     1657                                2500
     1658                        );
     1659                };
     1660                var fallback = function () {
     1661                        var box   = el( 'textarea', { class: 'screen-reader-text', readonly: 'readonly' } );
     1662                        box.value = text;
     1663                        document.body.appendChild( box );
     1664                        box.select();
     1665                        var ok = false;
     1666                        try {
     1667                                ok = document.execCommand( 'copy' );
     1668                        } catch ( e ) {
     1669                                ok = false;
     1670                        }
     1671                        document.body.removeChild( box );
     1672                        if ( ok ) {
     1673                                done();
     1674                        } else {
     1675                                window.prompt( __( 'Copy the summary:', 'airworthy' ), text );
     1676                        }
     1677                };
     1678                if ( navigator.clipboard && window.isSecureContext ) {
     1679                        navigator.clipboard.writeText( text ).then( done, fallback );
     1680                } else {
     1681                        fallback();
     1682                }
     1683        }
     1684
     1685        /**
     1686         * "Did Airworthy help?" below the results of a finished scan. Asked once per user: Leave a
     1687         * review and Don't ask again end it, Maybe later asks again in 30 days.
     1688         */
     1689        function reviewCard() {
     1690                var card   = null;
     1691                var answer = function ( choice ) {
     1692                        config.review = null; // Not again on this page.
     1693                        if ( card && card.parentNode ) {
     1694                                card.parentNode.removeChild( card );
     1695                        }
     1696                        apiFetch( { path: REST + '/review', method: 'POST', data: { choice: choice } } ).catch( function () {} );
     1697                        if ( 'done' !== choice ) {
     1698                                announce( __( 'Thanks. Airworthy won\'t ask again for now.', 'airworthy' ) );
     1699                        }
     1700                };
     1701                card       = el(
     1702                        'div',
     1703                        { class: 'airworthy-card airworthy-review' },
     1704                        el( 'h3', null, __( 'Did Airworthy help?', 'airworthy' ) ),
     1705                        el( 'p', null, __( 'Airworthy is free. A short review on WordPress.org helps other site owners find it before their own PHP upgrade, and takes about a minute.', 'airworthy' ) ),
     1706                        el(
     1707                                'p',
     1708                                { class: 'airworthy-review-actions' },
     1709                                el(
     1710                                        'a',
     1711                                        { class: 'button button-primary', href: config.review.url, target: '_blank', rel: 'noopener', onclick: function () {
     1712                                                answer( 'done' );
     1713                                        } },
     1714                                        __( 'Leave a review', 'airworthy' ),
     1715                                        el( 'span', { class: 'screen-reader-text' }, __( '(opens in a new tab)', 'airworthy' ) )
     1716                                ),
     1717                                el(
     1718                                        'button',
     1719                                        { type: 'button', class: 'button-link', onclick: function () {
     1720                                                answer( 'later' );
     1721                                        } },
     1722                                        __( 'Maybe later', 'airworthy' )
     1723                                ),
     1724                                el(
     1725                                        'button',
     1726                                        { type: 'button', class: 'button-link', onclick: function () {
     1727                                                answer( 'never' );
     1728                                        } },
     1729                                        __( 'Don\'t ask again', 'airworthy' )
     1730                                )
     1731                        )
     1732                );
     1733                return card;
    15511734        }
    15521735
  • airworthy/trunk/readme.txt

    r3739681 r3751048  
    55Tested up to: 7.1
    66Requires PHP: 7.2
    7 Stable tag: 1.0.0
     7Stable tag: 1.0.1
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    2222
    2323* **A verdict for every plugin and theme.** Blocker, Unknown, Suppressed, Guarded, Warnings or Ready, each with one plain sentence explaining what it means for you.
    24 * **Fewer false alarms.** Many plugins carry old code that only runs on old PHP versions, behind a version check. Airworthy recognises those checks and marks that code as guarded instead of broken. In our test of the 30 most popular plugins, this cut the plugins flagged as broken from 4 to 2, and in both the flagged code really would fail on PHP 8.
     24* **Fewer false alarms.** Many plugins carry old code that only runs on old PHP versions, behind a version check. Airworthy recognises those checks and marks that code as guarded instead of broken. In our test of the 30 most popular plugins, this cut the plugins flagged as broken from 4 to 2, and both of those contain code that really would fail on PHP 8.
    2525* **Maintenance signals from WordPress.org (if you allow it).** Plugins that were closed (removed from the directory), not updated in two years, not tested with recent WordPress versions, or that need a newer PHP version than you picked are called out.
    2626* **Know what to do next.** Results are grouped into fix before you upgrade, keep an eye on, and all good. Plugins with an update waiting say so, with a one-click update, and Airworthy checks them again once they're updated.
    2727* **Know how long you have.** Airworthy shows when your server's PHP version stops getting security fixes, so you can plan the upgrade before it's urgent.
    28 * **The details when you want them.** Every finding shows the file, the line and what changed in PHP. Filter by verdict, rescan one plugin after an update, or download everything as a CSV file for your developer or host.
     28* **The details when you want them.** Every finding shows the file, the line and what changed in PHP. Filter by verdict, rescan one plugin after an update, copy a plain-text summary to paste into an email or support ticket, or download everything as a CSV file for your developer or host.
    2929* **Sensible default.** Airworthy recommends the oldest PHP version that still gets security fixes: the smallest upgrade that keeps your site protected. It shows every version's support dates.
    3030* **Safe on any host.** Scans run in the background in short batches, so they never time out, and they watch memory use. You can leave the page while a scan runs. Nothing is changed on your site.
    … …  
    3232* **In Site Health too.** Tools > Site Health shows whether your plugins and themes are ready for the next PHP version, with a link to the full results.
    3333* **Multisite ready.** On a network, Airworthy is activated network-wide and lives under Network Admin > Settings.
     34
     35= For freelancers and agencies =
     36
     37Hosts are moving sites off old PHP versions, and every client asks the same question: will my site break? Install Airworthy on each client site before the host's deadline (it's free, on as many sites as you like), and you have an answer per plugin in minutes. Copy summary gives you a plain-text list to paste into the client email or the host's support ticket, the CSV has every finding for your developer, and the Site Health check keeps showing whether the site is ready for the next PHP version. For many sites at once, use WP-CLI.
    3438
    3539= WP-CLI =
    … …  
    136140That menu comes from Action Scheduler, the background-job library Airworthy uses (WooCommerce uses the same one). It's harmless, and lists Airworthy's jobs under the "airworthy" group.
    137141
     142= Can I use Airworthy on client sites? =
     143
     144Yes. Airworthy is free and GPL-licensed, with no limit on sites and no account. Agencies often run it from WP-CLI (`wp airworthy scan --target=8.4 --fail-on=blocker`) across all their sites, and use Copy summary or the CSV export for each client.
     145
    138146= How do I report a security problem? =
    139147
    … …  
    1481565. Settings: skip inactive plugins, never check chosen plugins or themes, and pick a scan speed that suits your hosting. Changes save as you make them.
    1491576. A PHP upgrade check in Tools > Site Health, next to WordPress's own checks.
     1587. The same check from WP-CLI, for agencies looking after many sites.
    150159
    151160== Changelog ==
     161
     162= 1.0.1 =
     163* New: Copy summary, next to Export CSV on the results. Copies a plain-text summary (the overall answer, then each plugin and theme grouped by what to do next, with updates waiting and closed plugins) to paste into an email or support ticket for your host or developer.
     164* New: after a finished scan, the results ask once whether you'd leave a review on WordPress.org. Maybe later asks again in 30 days; Don't ask again means never. It only appears on Airworthy's own screen, below the results.
     165* PHP support dates checked against php.net on 16 October 2026: PHP 8.2 gets security fixes until 31 December 2026.
     166* WP-CLI: the note about problems that already apply on your current PHP version now says how to list them (`wp airworthy results --fields=name,verdict,existing`); it pointed to a column the scan table doesn't show.
    152167
    153168= 1.0.0 =
    … …  
    167182== Upgrade Notice ==
    168183
     184= 1.0.1 =
     185Adds Copy summary on the results, for sending to your host or developer.
     186
    169187= 1.0.0 =
    170188First release.
  • airworthy/trunk/sbom.cdx.json

    r3722113 r3751048  
    44    "version": 1,
    55    "metadata": {
    6         "timestamp": "2026-09-30T21:58:36Z",
     6        "timestamp": "2026-10-16T19:45:22Z",
    77        "component": {
    88            "type": "application",
    9             "bom-ref": "pkg:wordpress-plugin/airworthy@1.0.0",
     9            "bom-ref": "pkg:wordpress-plugin/airworthy@1.0.1",
    1010            "name": "airworthy",
    11             "version": "1.0.0",
     11            "version": "1.0.1",
    1212            "description": "Airworthy – PHP Compatibility & Upgrade Checker (WordPress plugin)",
    1313            "licenses": [
    … …  
    209209    "dependencies": [
    210210        {
    211             "ref": "pkg:wordpress-plugin/airworthy@1.0.0",
     211            "ref": "pkg:wordpress-plugin/airworthy@1.0.1",
    212212            "dependsOn": [
    213213                "pkg:composer/phpcompatibility/php-compatibility@10.0.0-alpha2",
  • airworthy/trunk/src/Admin/Page.php

    r3722113 r3751048  
    8282                                        'cronDisabled'   => defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON,
    8383                                        'resultsActions' => self::results_actions(),
     84                                        'review'         => Review::config(),
     85                                        'pluginUrl'      => 'https://wordpress.org/plugins/airworthy/',
    8486                                )
    8587                        ) . ';',
  • airworthy/trunk/src/Cli/Command.php

    r3722113 r3751048  
    529529                        $existing = array_sum( wp_list_pluck( $this->components( $scan_id ), 'existing' ) );
    530530                        if ( $existing && ! empty( $scan->from_php ) ) {
    531                                 WP_CLI::log( sprintf( '%1$d problems already apply on PHP %2$s, so they are not caused by this upgrade (see the "existing" column).', $existing, $scan->from_php ) );
     531                                WP_CLI::log(
     532                                        sprintf(
     533                                                1 === $existing ?
     534                                                '%1$d problem already applies on PHP %2$s, so it is not caused by this upgrade. To see where: wp airworthy results --fields=name,verdict,existing' :
     535                                                '%1$d problems already apply on PHP %2$s, so they are not caused by this upgrade. To see where: wp airworthy results --fields=name,verdict,existing',
     536                                                $existing,
     537                                                $scan->from_php
     538                                        )
     539                                );
    532540                        }
    533541                        if ( in_array( $scan->wporg_status, array( 'offline', 'partial' ), true ) ) {
  • airworthy/trunk/src/Installer.php

    r3722113 r3751048  
    199199                        delete_site_option( $option );
    200200                }
     201                \Airworthy\Admin\Review::forget_all(); // Each user's answer to the review request.
    201202
    202203                // Cached WordPress.org lookups. They're site transients, which live in the options table
  • airworthy/trunk/src/Rest/Controller.php

    r3722113 r3751048  
    217217                                'permission_callback' => $can,
    218218                                'args'                => array( 'id' => $id ),
     219                        )
     220                );
     221                register_rest_route(
     222                        $ns,
     223                        '/review',
     224                        array(
     225                                'methods'             => 'POST',
     226                                'callback'            => array( \Airworthy\Admin\Review::class, 'rest_answer' ),
     227                                'permission_callback' => $can,
     228                                'args'                => array(
     229                                        'choice' => array(
     230                                                'required'    => true,
     231                                                'type'        => 'string',
     232                                                'enum'        => \Airworthy\Admin\Review::CHOICES,
     233                                                'description' => __( 'The user\'s answer to the review request: done, later or never.', 'airworthy' ),
     234                                        ),
     235                                ),
    219236                        )
    220237                );
  • airworthy/trunk/src/Targets.php

    r3722113 r3751048  
    3838
    3939        /** When SECURITY_UNTIL was last checked against php.net. */
    40         const TABLE_CHECKED = '2026-09-29';
     40        const TABLE_CHECKED = '2026-10-16';
    4141
    4242        /**
  • airworthy/trunk/vendor/composer/installed.php

    r3722113 r3751048  
    33namespace Airworthy\Vendor;
    44
    5 return array('root' => array('name' => 'digitalkind/airworthy', 'pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '8ed4539c1fdedf95361a42ed753e4a4897ecf320', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \false), 'versions' => array('dealerdirect/phpcodesniffer-composer-installer' => array('pretty_version' => 'v1.2.1', 'version' => '1.2.1.0', 'reference' => '963f0c67bffde0eac41b56be71ac0e8ba132f0bd', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../dealerdirect/phpcodesniffer-composer-installer', 'aliases' => array(), 'dev_requirement' => \false), 'digitalkind/airworthy' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '8ed4539c1fdedf95361a42ed753e4a4897ecf320', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/php-compatibility' => array('pretty_version' => '10.0.0-alpha2', 'version' => '10.0.0.0-alpha2', 'reference' => 'e0f0e5a3dc819a4a0f8d679a0f2453d941976e18', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/php-compatibility', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/phpcompatibility-paragonie' => array('pretty_version' => '2.0.0-alpha2', 'version' => '2.0.0.0-alpha2', 'reference' => '7a979711c87d8202b52f56c56bd719d09d8ed7f5', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/phpcompatibility-paragonie', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/phpcompatibility-wp' => array('pretty_version' => '3.0.0-alpha2', 'version' => '3.0.0.0-alpha2', 'reference' => 'bd53f24e7528422ac51d64dc8d53e8d4c4a877b3', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/phpcompatibility-wp', 'aliases' => array(), 'dev_requirement' => \false), 'phpcsstandards/phpcsutils' => array('pretty_version' => '1.2.3', 'version' => '1.2.3.0', 'reference' => '5f35d9408c54d7b529501f3c688b6eae562aea1f', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcsstandards/phpcsutils', 'aliases' => array(), 'dev_requirement' => \false), 'squizlabs/php_codesniffer' => array('pretty_version' => '4.0.4', 'version' => '4.0.4.0', 'reference' => 'bbdc3d0532623e21838b7041a4364383a8126f96', 'type' => 'library', 'install_path' => __DIR__ . '/../squizlabs/php_codesniffer', 'aliases' => array(), 'dev_requirement' => \false), 'wimg/php-compatibility' => array('dev_requirement' => \false, 'replaced' => array(0 => '*')), 'woocommerce/action-scheduler' => array('pretty_version' => '4.2.0', 'version' => '4.2.0.0', 'reference' => '9e2c6b02e89652bade4445ea2ca5fb12e0fa7242', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../woocommerce/action-scheduler', 'aliases' => array(), 'dev_requirement' => \false)));
     5return array('root' => array('name' => 'digitalkind/airworthy', 'pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '9c9a53d3656967dc5abc254b265e07368204d493', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => \false), 'versions' => array('dealerdirect/phpcodesniffer-composer-installer' => array('pretty_version' => 'v1.2.1', 'version' => '1.2.1.0', 'reference' => '963f0c67bffde0eac41b56be71ac0e8ba132f0bd', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../dealerdirect/phpcodesniffer-composer-installer', 'aliases' => array(), 'dev_requirement' => \false), 'digitalkind/airworthy' => array('pretty_version' => 'dev-main', 'version' => 'dev-main', 'reference' => '9c9a53d3656967dc5abc254b265e07368204d493', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/php-compatibility' => array('pretty_version' => '10.0.0-alpha2', 'version' => '10.0.0.0-alpha2', 'reference' => 'e0f0e5a3dc819a4a0f8d679a0f2453d941976e18', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/php-compatibility', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/phpcompatibility-paragonie' => array('pretty_version' => '2.0.0-alpha2', 'version' => '2.0.0.0-alpha2', 'reference' => '7a979711c87d8202b52f56c56bd719d09d8ed7f5', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/phpcompatibility-paragonie', 'aliases' => array(), 'dev_requirement' => \false), 'phpcompatibility/phpcompatibility-wp' => array('pretty_version' => '3.0.0-alpha2', 'version' => '3.0.0.0-alpha2', 'reference' => 'bd53f24e7528422ac51d64dc8d53e8d4c4a877b3', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcompatibility/phpcompatibility-wp', 'aliases' => array(), 'dev_requirement' => \false), 'phpcsstandards/phpcsutils' => array('pretty_version' => '1.2.3', 'version' => '1.2.3.0', 'reference' => '5f35d9408c54d7b529501f3c688b6eae562aea1f', 'type' => 'phpcodesniffer-standard', 'install_path' => __DIR__ . '/../phpcsstandards/phpcsutils', 'aliases' => array(), 'dev_requirement' => \false), 'squizlabs/php_codesniffer' => array('pretty_version' => '4.0.4', 'version' => '4.0.4.0', 'reference' => 'bbdc3d0532623e21838b7041a4364383a8126f96', 'type' => 'library', 'install_path' => __DIR__ . '/../squizlabs/php_codesniffer', 'aliases' => array(), 'dev_requirement' => \false), 'wimg/php-compatibility' => array('dev_requirement' => \false, 'replaced' => array(0 => '*')), 'woocommerce/action-scheduler' => array('pretty_version' => '4.2.0', 'version' => '4.2.0.0', 'reference' => '9e2c6b02e89652bade4445ea2ca5fb12e0fa7242', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../woocommerce/action-scheduler', 'aliases' => array(), 'dev_requirement' => \false)));
Note: See TracChangeset for help on using the changeset viewer.