@@ -16,7 +16,57 @@ final class Plugin {
1616 * @codeCoverageIgnore
1717 */
1818 public function load_integrations () {
19- new Integrations ();
19+ $ this ->load_service ( Integrations::class );
20+ }
21+
22+ /**
23+ * Instantiates a service class without taking down the site when its file can't be loaded.
24+ *
25+ * WordPress' updater deletes the plugin directory before copying the new version into place, so a
26+ * request landing in that window finds part of our source tree missing. Because
27+ * @see register_services() runs on plugins_loaded for every request, an unguarded `new` turns that
28+ * into a fatal error on the front end instead of a single disabled feature.
29+ *
30+ * Note that `::class` is resolved at compile time and doesn't trigger the autoloader, so passing a
31+ * missing class here is safe.
32+ *
33+ * @since 2.6.1
34+ *
35+ * @param string $class_name Fully qualified class name.
36+ *
37+ * @return object|null Null when the class couldn't be loaded.
38+ */
39+ private function load_service ( $ class_name ) {
40+ if ( ! class_exists ( $ class_name ) ) {
41+ $ this ->log_missing_service ( $ class_name );
42+
43+ return null ;
44+ }
45+
46+ return new $ class_name ();
47+ }
48+
49+ /**
50+ * Logs a service that couldn't be loaded by @see load_service().
51+ *
52+ * Only logged when WP_DEBUG is enabled: during a plugin update this is expected and transient, and
53+ * we don't want to fill production logs with it.
54+ *
55+ * @since 2.6.1
56+ *
57+ * @param string $class_name Fully qualified class name.
58+ *
59+ * @return void
60+ *
61+ * @codeCoverageIgnore
62+ */
63+ private function log_missing_service ( $ class_name ) {
64+ if ( ! defined ( 'WP_DEBUG ' ) || ! WP_DEBUG ) {
65+ return ;
66+ }
67+
68+ // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
69+ error_log ( sprintf ( 'Plausible Analytics: %s could not be loaded and was skipped. ' , $ class_name ) );
2070 }
2171
2272 /**
@@ -44,8 +94,8 @@ public function load_plugin_textdomain() {
4494 * @codeCoverageIgnore
4595 */
4696 public function load_provisioning () {
47- new Admin \Provisioning ( );
48- new Admin \Provisioning \Integrations ( );
97+ $ this -> load_service ( Admin \Provisioning::class );
98+ $ this -> load_service ( Admin \Provisioning \Integrations::class );
4999 }
50100
51101 /**
@@ -56,7 +106,7 @@ public function load_provisioning() {
56106 * @codeCoverageIgnore
57107 */
58108 public function load_settings () {
59- new Admin \Settings \Page ( );
109+ $ this -> load_service ( Admin \Settings \Page::class );
60110 }
61111
62112 /**
@@ -82,7 +132,7 @@ public function register() {
82132 * @return void
83133 */
84134 public function setup () {
85- new Setup ( );
135+ $ this -> load_service ( Setup::class );
86136 }
87137
88138 /**
@@ -93,26 +143,25 @@ public function setup() {
93143 * @return void
94144 */
95145 public function register_services () {
96-
97146 if ( is_admin () ) {
98147 add_action ( 'init ' , [ $ this , 'load_settings ' ] );
99148 add_action ( 'init ' , [ $ this , 'load_provisioning ' ] );
100149
101- new Admin \Upgrades ( );
102- new Admin \Filters ( );
103- new Admin \Actions ( );
104- new Admin \Module ( );
105- new Admin \PrivacyPolicy ( );
150+ $ this -> load_service ( Admin \Upgrades::class );
151+ $ this -> load_service ( Admin \Filters::class );
152+ $ this -> load_service ( Admin \Actions::class );
153+ $ this -> load_service ( Admin \Module::class );
154+ $ this -> load_service ( Admin \PrivacyPolicy::class );
106155 }
107156
108157 add_action ( 'init ' , [ $ this , 'load_integrations ' ] );
109158
110- new AdminBar ( );
111- new Assets ( );
112- new Ajax ( );
113- new Compatibility ( );
114- new InitOptions ( );
115- new Proxy ( );
116- new Verification ( );
159+ $ this -> load_service ( AdminBar::class );
160+ $ this -> load_service ( Assets::class );
161+ $ this -> load_service ( Ajax::class );
162+ $ this -> load_service ( Compatibility::class );
163+ $ this -> load_service ( InitOptions::class );
164+ $ this -> load_service ( Proxy::class );
165+ $ this -> load_service ( Verification::class );
117166 }
118167}
0 commit comments