'collision.fatal', 'noticed' => 'It uses the same code names as a plugin that is already running.', 'why' => 'If both are on at once, PHP stops with a "Cannot redeclare" error and your site can stop loading.', 'worry' => 'fix', 'do' => 'Do not switch both on. Ask the author whether the two are meant to run together.', ), array( 'k' => 'collision.twin', 'noticed' => 'This looks like a second copy of a plugin you already run.', 'why' => 'Two copies in different folders use the same code names. Switched on together, they crash the site.', 'worry' => 'fix', 'do' => 'Keep one. If this is a newer copy, replace the old one instead of installing beside it.', ), array( 'k' => 'collision.shared', 'noticed' => '{plugins} share a helper that was built to be shared.', 'why' => 'Many WooCommerce plugins include the same Automattic helper for loading code. WordPress uses one copy, normally the newest. This is how most of them work.', 'worry' => 'fine', 'do' => 'Nothing. If something odd happens after you switch it on, this is one place to look.', ), array( 'k' => 'collision.libs', 'noticed' => 'It carries the same bundled library as a plugin you already run.', 'why' => 'Libraries loaded the usual way normally do not clash. But one plugin can end up using the other plugin\'s copy, and that may be a different version.', 'worry' => 'look', 'do' => 'Nothing to fix now. If something misbehaves after you switch it on or update it, look here first.', ), array( 'k' => 'collision.constants', 'noticed' => 'It sets a setting name that another plugin also sets.', 'why' => 'PHP shows a notice and keeps the first value. That is harmless unless the two plugins mean different things by it.', 'worry' => 'look', 'do' => 'Check that the shared setting does not carry different values.', ), array( 'k' => 'collision.pending', 'noticed' => 'Still comparing it with your other plugins.', 'why' => 'Big plugins take a few steps to read. Until that finishes, a clash could still be hiding.', 'worry' => 'unknown', 'do' => 'Wait. This page carries on by itself. Decide after it finishes.', ), array( 'k' => 'collision.partial', 'noticed' => 'I could not compare it with every plugin in full.', 'why' => 'Some plugin files were too many or too large to read, so a clash in those files would not show here.', 'worry' => 'unknown', 'do' => 'Test on a staging copy with those plugins switched on.', ), array( 'k' => 'collision.clear', 'noticed' => 'No shared code names with your other plugins.', 'why' => 'That removes the most common reason a new plugin crashes a site. It does not show the plugins work well together.', 'do' => 'Still try it on a staging copy.', ), array( 'k' => 'collision.alone', 'noticed' => 'There are no other active plugins to clash with.', 'why' => 'Nothing to compare against.', 'do' => '', ), array( 'k' => 'collision.none', 'noticed' => 'It adds no code names that could clash.', 'why' => 'In the files I read, it declares nothing at the top level that another plugin could also declare.', 'do' => '', ), /* ---------------------------------------------------------------- requirements. */ array( 'k' => 'req.version.undeclared', 'noticed' => 'The author does not say which {noun} version it needs.', 'why' => 'So I cannot tell whether it fits your site. A missing rule does not mean it will break. Small or older plugins often leave it out.', 'worry' => 'fine', 'do' => 'Nothing to fix. A staging test will tell you more than the number would.', ), array( 'k' => 'req.version.unreadable', 'noticed' => 'The {noun} version rule is written in a way I cannot read.', 'why' => 'I cannot compare it with your site.', 'worry' => 'look', 'do' => 'Read the version rule yourself on the plugin page.', ), array( 'k' => 'req.version.ok', 'noticed' => 'Your site meets the {noun} version it asks for.', 'why' => 'That is the author\'s statement. It does not prove the plugin works on your site.', 'do' => '', ), array( 'k' => 'req.version.unmet', 'noticed' => 'It needs a newer {noun} than your site has.', 'why' => 'It may not load, or it may crash the site.', 'worry' => 'fix', 'do' => 'Update {noun} first, or choose a release that supports your version.', ), array( 'k' => 'req.version.missing', 'noticed' => 'It needs {noun}, which is not active on this site.', 'why' => 'Its features will not work without it, and it may show errors.', 'worry' => 'fix', 'do' => 'Install and switch on {noun} first.', ), array( 'k' => 'req.tested.old', 'noticed' => 'The author has not tested it on your WordPress version.', 'why' => 'It may still work. Newer WordPress versions sometimes break older plugins.', 'worry' => 'look', 'do' => 'Check the changelog or the support forum for your WordPress version.', ), array( 'k' => 'req.tested.near', 'noticed' => 'The author tested it on a slightly older WordPress than yours.', 'why' => 'WordPress ships a new version every few months, so being one version ahead is normal. It is the author\'s statement, not a test I ran.', 'worry' => 'fine', 'do' => 'Nothing to fix. A quick look at the changelog is enough.', ), array( 'k' => 'req.tested.ok', 'noticed' => 'The author says it was tested on your WordPress version.', 'why' => 'That is a statement, not a test I ran.', 'do' => '', ), array( 'k' => 'req.plugin.ok', 'noticed' => 'It needs {slug}, and {slug} is installed and active.', 'why' => 'How the two work together is not tested.', 'do' => '', ), array( 'k' => 'req.plugin.inactive', 'noticed' => 'It needs {slug}, which is installed but switched off.', 'why' => 'Without it, this plugin may not work or may show errors.', 'worry' => 'look', 'do' => 'Switch on {slug} first, then check that everything looks right.', ), array( 'k' => 'req.plugin.missing', 'noticed' => 'It needs {slug}, which is not installed.', 'why' => 'Without it, this plugin will not work and may stop the site loading.', 'worry' => 'fix', 'do' => 'Install {slug} first, then this plugin.', ), array( 'k' => 'req.woo.ok', 'noticed' => 'It works with WooCommerce, and WooCommerce is active here.', 'why' => 'Whether the two work together is not tested.', 'do' => '', ), array( 'k' => 'req.woo.off', 'noticed' => 'It looks like it needs WooCommerce, which is not active here.', 'why' => 'Its store features will not work without it.', 'worry' => 'look', 'do' => 'Install and switch on WooCommerce first.', ), array( 'k' => 'req.dep.ok', 'noticed' => 'It has code that works with {slug}, and {slug} is active.', 'why' => 'Whether the two work together is not tested.', 'do' => '', ), array( 'k' => 'req.dep.off', 'noticed' => 'It has code that works with {slug}, which is not ready here.', 'why' => 'Many plugins add extra features when another plugin is there and run fine without it. The author does not list {slug} as required, and I cannot tell which this is.', 'worry' => 'fine', 'do' => 'If you plan to use it with {slug}, set that up first. Otherwise nothing to do.', ), array( 'm' => 'Integrations detected in the code', 'noticed' => 'It mentions several other plugins.', 'why' => 'Plugins like this usually run without each one, but I cannot tell which it really needs.', 'worry' => 'fine', 'do' => 'Test it on a staging copy with the ones you use.', ), array( 'm' => 'WooCommerce compatibility', 'noticed' => 'WordPress.org does not list this plugin\'s WooCommerce details.', 'why' => 'I cannot tell which WooCommerce versions or checkout types it supports.', 'worry' => 'unknown', 'do' => 'Read the plugin page and test checkout on a staging copy.', ), array( 'm' => 'Package version', 'noticed' => 'The update says one version, but the files say another.', 'why' => 'A mismatch like that can mean a wrong or tampered package.', 'worry' => 'fix', 'do' => 'Do not update until the author explains it. Check the plugin page for the current release.', ), array( 'm' => 'Package folder', 'noticed' => 'The update unpacks into a different folder than the plugin you run.', 'why' => 'WordPress would install it as a separate plugin, not replace yours.', 'worry' => 'fix', 'do' => 'Do not update. Check the plugin page for the right download.', ), array( 'm' => 'Archive paths', 'noticed' => 'The ZIP tries to write files outside the plugin folder.', 'why' => 'That is a known trick for planting files elsewhere on a server. WordPress refuses such ZIPs.', 'worry' => 'fix', 'do' => 'Do not install it. Treat it as a warning sign.', ), array( 'm' => 'Folder name', 'noticed' => 'The ZIP\'s folder name looks like a download copy, not a plugin name.', 'why' => 'WordPress installs it under that name, so later updates may not line up.', 'worry' => 'look', 'do' => 'Get the author\'s release ZIP, or rename the folder and zip it again.', ), /* ---------------------------------------------------------------- WooCommerce. */ array( 'k' => 'woo.declared.ok', 'noticed' => 'The author says it works with this WooCommerce feature.', 'why' => 'That is their word, not a test.', 'do' => 'Test it on a staging copy if this feature matters to you.', ), array( 'k' => 'woo.declared.no.use', 'noticed' => 'The author says it does not work with a feature your store uses.', 'why' => 'Parts of checkout or orders could break.', 'worry' => 'fix', 'do' => 'Do not switch it on here, or ask the author for a compatible release.', ), array( 'k' => 'woo.declared.no', 'noticed' => 'The author says it does not work with a WooCommerce feature your store does not use.', 'why' => 'Fine today. It becomes a problem if you turn that feature on later.', 'worry' => 'look', 'do' => 'Do not turn that feature on while this plugin is active.', ), array( 'k' => 'woo.declared.none', 'noticed' => 'The author does not say whether it works with this WooCommerce feature.', 'why' => 'That is not a failure, but WooCommerce may show a warning about this plugin.', 'worry' => 'look', 'do' => 'Test it on a staging copy with that feature on.', ), array( 'k' => 'entry.hooks', 'noticed' => 'It changes checkout through WooCommerce hooks.', 'why' => 'Plugins that change the same part of checkout can get in each other\'s way. I did not compare them with your other plugins.', 'worry' => 'fine', 'do' => 'Run one full test checkout on a staging copy.', ), array( 'k' => 'req.php.syntax', 'noticed' => 'Some of its code looks written for a newer PHP than this site runs.', 'why' => 'On an older PHP, one such file can stop the whole site with a fatal error. I read patterns in the code, so I may be wrong.', 'worry' => 'fix', 'do' => 'Try it on a staging copy first, or ask your host to move this site to a newer PHP.', ), array( 'k' => 'pkg.oddfiles', 'noticed' => 'The package has programs or scripts in it, such as .exe, .sh or .py files.', 'why' => 'A WordPress plugin normally only needs PHP, JavaScript, CSS and images. Some are harmless build leftovers. I did not open or run them, so I cannot tell which these are.', 'worry' => 'look', 'do' => 'Ask the author why they are there, or install only a copy from the official plugin directory.', ), array( 'k' => 'woo.declared.ownfiles', 'noticed' => 'I found no statement about this WooCommerce feature in the plugin\'s own code.', 'why' => 'I skipped some bundled libraries and test files. That is not a failure, but WooCommerce may show a warning about this plugin.', 'worry' => 'look', 'do' => 'Test it on a staging copy with that feature on.', ), array( 'k' => 'woo.declared.partial', 'noticed' => 'I read only part of it, so I cannot say whether it declares this.', 'why' => 'The answer could be in the part I did not read.', 'worry' => 'unknown', 'do' => 'Ask the author, or check the changelog.', ), array( 'k' => 'woo.declared.unread', 'noticed' => 'I could not read its code for this.', 'why' => 'So I cannot say whether it declares support.', 'worry' => 'unknown', 'do' => 'Ask the author, or check the changelog.', ), array( 'k' => 'woo.tested.old', 'noticed' => 'It was tested on an older WooCommerce than the one you run.', 'why' => 'Newer WooCommerce releases sometimes change things plugins rely on, most often in checkout.', 'worry' => 'look', 'do' => 'Check the changelog or support forum for your WooCommerce version.', ), array( 'k' => 'woo.tested.near', 'noticed' => 'The author tested it on a slightly older WooCommerce than yours.', 'why' => 'WooCommerce ships a release most months, so being one or two releases ahead is normal. It is the author\'s statement, not a test I ran.', 'worry' => 'fine', 'do' => 'Nothing to fix. A test order on a staging copy will tell you more.', ), array( 'k' => 'woo.tested.ok', 'noticed' => 'Its WooCommerce "tested up to" fits your version.', 'why' => 'That is the author\'s statement, not a test.', 'do' => '', ), array( 'k' => 'woo.tested.unreadable', 'noticed' => 'I could not read the WooCommerce version it says it was tested on.', 'why' => 'So I cannot compare it with your store.', 'worry' => 'look', 'do' => 'Check the changelog for supported WooCommerce versions.', ), array( 'k' => 'woo.tested.nowoo', 'noticed' => 'WooCommerce is not active here, so there is nothing to compare its tested version with.', 'why' => 'I cannot say whether it fits.', 'worry' => 'unknown', 'do' => 'Compare it with the WooCommerce version you plan to run.', ), array( 'm' => 'Order data access', 'noticed' => 'It appears to read or write orders the old way.', 'why' => 'If your store uses (or later turns on) the newer order storage, orders could go missing or fail.', 'worry' => 'look', 'do' => 'Create, edit and refund a test order on a staging copy before you rely on it.', ), /* ---------------------------------------------------------------- code findings. */ array( 'k' => 'entry.open', 'noticed' => 'Some public doors have no lock I can see.', 'why' => 'These are places anyone on the internet can call. Without a check on who is calling, someone could read or change things. A missing lock may just be in another file.', 'worry' => 'look', 'do' => 'Ask the author how each one checks who is calling.', ), array( 'k' => 'entry.open.pay', 'noticed' => 'Some payment callbacks have no lock I can see.', 'why' => 'Payment callbacks have to be public, but they should check who is sending them. Otherwise someone could fake a payment message.', 'worry' => 'look', 'do' => 'Ask the author how each one checks the sender.', ), array( 'k' => 'entry.ok', 'noticed' => 'No public door without a lock in the files I read.', 'why' => 'I look for a permission or signature check next to each public entry. That checks patterns in the code, not behaviour. It cannot see code built while the plugin runs.', 'do' => '', ), array( 'k' => 'entry.update', 'noticed' => 'The new version adds or changes public doors.', 'why' => 'Each one is a place anyone online can call. New ones deserve a look, mainly if they lack a check on who is calling.', 'worry' => 'look', 'do' => 'Read the changelog for why they were added.', ), array( 'k' => 'entry.update.ok', 'noticed' => 'The new version adds no public doors.', 'why' => 'That compares patterns in the files. It does not say the existing ones are safe.', 'do' => '', ), array( 'k' => 'hosts.new', 'noticed' => 'The new version names outside websites the old one did not.', 'why' => 'It could be a new service the plugin talks to, such as analytics or a licence server. A name in the code does not mean it calls it.', 'worry' => 'look', 'do' => 'Check the changelog for a new service.', ), array( 'k' => 'abilities.new', 'noticed' => 'The new version can do things the old one could not.', 'why' => 'For example scheduled jobs, changes to your database, or requests to other sites. These are patterns in the code, not proof of behaviour.', 'worry' => 'look', 'do' => 'Read the changelog, then try the update on a staging copy.', ), array( 'k' => 'abilities.same', 'noticed' => 'Nothing new in what the code can do.', 'why' => 'I found no pattern that the version you run does not already have.', 'do' => '', ), array( 'm' => 'Checkout block payment method', 'noticed' => 'Its payment method may not show up in the Checkout block.', 'why' => 'If your checkout uses the block, customers might not see it as a way to pay.', 'worry' => 'look', 'do' => 'Test the checkout page on a staging copy.', ), array( 're' => '~ minimum raised$~', 's' => array( 'pass' ), 'noticed' => 'The new version asks for a newer {noun}, and your site already has it.', 'why' => 'No problem today. It does narrow where you can move this plugin later.', 'do' => '', ), array( 're' => '~ minimum raised$~', 'noticed' => 'The new version asks for a newer {noun} than your site has.', 'why' => 'It may fail to load or crash the site.', 'worry' => 'fix', 'do' => 'Update {noun} first, or stay on the version you run.', ), array( 'm' => 'The installed version was not fully read', 'noticed' => 'I could only read part of the version you run.', 'why' => 'Something the new version adds in a part I could not read may show as a change when it is not.', 'worry' => 'unknown', 'do' => '', ), array( 'm' => 'Changes since your installed version', 'noticed' => 'I could not compare the new version with yours.', 'why' => 'So I cannot say what the update changes in the code.', 'worry' => 'unknown', 'do' => 'Read the changelog and try the update on a staging copy.', ), array( 'm' => 'Part of the package was not read', 'noticed' => 'I could not read all of it.', 'why' => 'Some files were too long or too many. Anything in the part I did not read is not in this review.', 'worry' => 'unknown', 'do' => '', ), array( 'm' => 'Customers may be checking out right now', 'noticed' => 'Customers may be paying right now.', 'why' => 'Changing a plugin while someone pays can interrupt their order.', 'worry' => 'look', 'do' => 'Wait until no checkout is open, or choose a quiet hour.', ), );