1+ <?php
2+
3+ /**
4+ * If your websites use PHP-FPM and you have incron installed, you can use this plugin to automatically add incron
5+ * configuration which will take care of reloading the php-fpm pool when the file /private/php-fpm.reload is touched.
6+ * Projects which use deployment tools can use this to reload php-fpm to clear the opcache at deploy time, without
7+ * requiring superuser privileges.
8+ */
9+ class incron_plugin {
10+
11+ var $ plugin_name = 'incron_plugin ' ;
12+ var $ class_name = 'incron_plugin ' ;
13+
14+ function onInstall () {
15+ global $ conf ;
16+
17+ if ($ conf ['services ' ]['web ' ] !== true ) {
18+ return false ;
19+ }
20+
21+ if ($ this ->isIncronAvailable () === false ) {
22+ return false ;
23+ }
24+
25+ return true ;
26+ }
27+
28+ function onLoad () {
29+ global $ app ;
30+
31+ $ app ->plugins ->registerEvent ('web_domain_insert ' , $ this ->plugin_name , 'incronInsert ' );
32+ $ app ->plugins ->registerEvent ('web_domain_update ' , $ this ->plugin_name , 'incronUpdate ' );
33+ $ app ->plugins ->registerEvent ('web_domain_delete ' , $ this ->plugin_name , 'incronDelete ' );
34+ }
35+
36+ function incronInsert ($ eventName , $ data ) {
37+ $ this ->setup ($ data ['new ' ]);
38+ }
39+
40+ function incronUpdate ($ eventName , $ data ) {
41+ global $ app ;
42+
43+ if ($ data ['new ' ]['document_root ' ] === $ data ['old ' ]['document_root ' ]) {
44+ $ app ->log ('Document root unchanged. Not updating incron configuration. ' , LOGLEVEL_DEBUG );
45+
46+ return ;
47+ }
48+
49+ $ this ->teardown ($ data ['old ' ]);
50+ $ this ->setup ($ data ['new ' ]);
51+ }
52+
53+ function incronDelete ($ eventName , $ data ) {
54+ $ this ->teardown ($ data ['old ' ]);
55+ }
56+
57+ private function setup ($ data )
58+ {
59+ $ triggerFile = $ this ->getTriggerFilePath ($ data ['document_root ' ]);
60+
61+ $ this ->createTriggerFile ($ triggerFile , $ data ['system_user ' ], $ data ['system_group ' ]);
62+ $ this ->createIncronConfiguration (
63+ $ triggerFile ,
64+ $ data ['system_user ' ],
65+ $ data ['fastcgi_php_version ' ]
66+ );
67+
68+ $ this ->restartIncronService ();
69+ }
70+
71+ private function teardown ($ data ) {
72+ $ this ->deleteIncronConfiguration ($ data ['system_user ' ]);
73+ $ this ->deleteTriggerFile ($ this ->getTriggerFilePath ($ data ['document_root ' ]));
74+
75+ $ file = sprintf ('/etc/incron.d/%s.conf ' , $ data ['system_user ' ]);
76+
77+ @unlink ($ file );
78+
79+ $ this ->restartIncronService ();
80+ }
81+
82+ private function isIncronAvailable () {
83+ exec ('which incrond ' , $ output , $ retval );
84+
85+ return $ retval === 0 ;
86+ }
87+
88+ private function createIncronConfiguration ($ triggerFile , $ systemUser , $ fastcgiPhpVersion ) {
89+ global $ app ;
90+
91+ $ phpService = $ this ->getPhpService ($ fastcgiPhpVersion );
92+ $ configFile = $ this ->getIncronConfigurationFilePath ($ systemUser );
93+
94+ $ content = sprintf (
95+ '%s %s %s ' ,
96+ $ triggerFile ,
97+ 'IN_CLOSE_WRITE ' ,
98+ $ app ->system ->getinitcommand ($ phpService , 'reload ' )
99+ );
100+
101+ file_put_contents ($ configFile , $ content );
102+
103+ $ app ->log (sprintf ('Created incron configuration "%s" ' , $ configFile ), LOGLEVEL_DEBUG );
104+ }
105+
106+ private function createTriggerFile ($ triggerFile , $ systemUser , $ systemGroup ) {
107+ global $ app ;
108+
109+ if (!file_exists ($ triggerFile )) {
110+ exec (sprintf ('touch %s ' , $ triggerFile ));
111+ }
112+
113+ exec (sprintf ('chown %s:%s %s ' , $ systemUser , $ systemGroup , $ triggerFile ));
114+
115+ $ app ->log (sprintf ('Ensured incron trigger file "%s" ' , $ triggerFile ), LOGLEVEL_DEBUG );
116+ }
117+
118+ private function deleteIncronConfiguration ($ systemUser ) {
119+ global $ app ;
120+
121+ $ configFile = $ this ->getIncronConfigurationFilePath ($ systemUser );
122+ unlink ($ configFile );
123+
124+ $ app ->log (sprintf ('Deleted incron configuration "%s" ' , $ configFile ), LOGLEVEL_DEBUG );
125+ }
126+
127+ private function deleteTriggerFile ($ triggerFile ) {
128+ global $ app ;
129+
130+ unlink ($ triggerFile );
131+
132+ $ app ->log (sprintf ('Deleted incron trigger file "%s" ' , $ triggerFile ), LOGLEVEL_DEBUG );
133+ }
134+
135+ private function getTriggerFilePath ($ documentRoot ) {
136+ return sprintf ('%s/private/php-fpm.reload ' , $ documentRoot );
137+ }
138+
139+ private function getIncronConfigurationFilePath ($ systemUser ) {
140+ return sprintf ('/etc/incron.d/%s.conf ' , $ systemUser );
141+ }
142+
143+ private function getPhpService ($ fastcgiPhpVersion ) {
144+ $ phpInfo = explode (': ' , $ fastcgiPhpVersion );
145+ if (empty ($ phpInfo )) {
146+ return null ;
147+ }
148+
149+ $ phpService = $ phpInfo [1 ];
150+ if (empty ($ phpService )) {
151+ return null ;
152+ }
153+
154+ return $ phpService ;
155+ }
156+
157+ private function restartIncronService () {
158+ global $ app ;
159+
160+ exec ($ app ->system ->getinitcommand ('incrond ' , 'restart ' ));
161+ }
162+ }
0 commit comments