· 9 years ago · Jan 14, 2017, 11:52 PM
1<?php
2
3/**
4 * Helper Brivium Addon for EventListener.
5 *
6 * @package Brivium_BriviumHelper
7 * Version 1.2.0
8 */
9abstract class Brivium_BriviumHelper_Installer
10{
11 protected $_db = null;
12 protected $_tables = null;
13 protected $_alters = null;
14 protected $_data = null;
15 protected $_triggerType = null;
16 protected $_queryBeforeTable = null;
17 protected $_queryBeforeAlter = null;
18 protected $_queryBeforeData = null;
19 protected $_queryFinal = null;
20 protected $_licenseData = null;
21 protected $_versionId = null;
22 protected $_existingVersionId = null;
23 protected $_preInstallCalled = null;
24 protected $_preUninstallCalled = null;
25 protected $_modelCache = array();
26 protected $_existingAddOn = array();
27 protected $_addOnToInstall = array();
28 protected $_installHash = null;
29 protected $_installerType = 1;
30 protected static $_addOnInstaller = null;
31
32 protected function _getDb()
33 {
34 if($this->_db === null){
35 $this->_db = XenForo_Application::get('db');
36 }
37 return $this->_db;
38 }
39
40 public function getAddOnToInstall()
41 {
42 return $this->_addOnToInstall;
43 }
44
45 public function getExistingAddOn()
46 {
47 return $this->_existingAddOn;
48 }
49
50 public function addColumn($table, $field, $attr)
51 {
52 if(!$this->checkIfExist($table, $field)){
53 return $this->_getDb()->query("ALTER TABLE `" . $table . "` ADD `" . $field . "` " . $attr);
54 }
55 }
56
57 public function removeColumn($table, $field)
58 {
59 if($this->checkIfExist($table, $field)){
60 return $this->_getDb()->query("ALTER TABLE `" . $table . "` DROP `" . $field . "`");
61 }
62 }
63
64 public function checkIfExist($table, $field)
65 {
66 if($this->_getDb()->fetchRow('SHOW columns FROM `' . $table . '` WHERE Field = ?', $field)){
67 return true;
68 }
69 else {
70 return false;
71 }
72 }
73
74 public function checkTableExist($table)
75 {
76 if($this->_getDb()->fetchRow('SHOW TABLES LIKE ?', $table)){
77 return true;
78 }
79 else {
80 return false;
81 }
82 }
83
84 public function initialize($existingAddOn = array(), $addOnToInstall = array(), $triggerType = 'install')
85 {
86 $this->_triggerType = $triggerType;
87 $this->_existingAddOn = $existingAddOn;
88 $this->_addOnToInstall = $addOnToInstall;
89 $this->_versionId = !empty($addOnToInstall['version_id'])?$addOnToInstall['version_id']:0;
90 $this->_existingVersionId = !empty($existingAddOn['version_id'])?$existingAddOn['version_id']:0;
91
92 if($triggerType=='install' && !$existingAddOn && $this->_installerType==1){
93 $this->_checkLicense();
94 }else{
95 $this->_initData();
96 }
97 }
98
99 /*
100 *
101 * Installer
102 *
103 */
104
105 public static function install($existingAddOn, $addOnData)
106 {
107 self::$_addOnInstaller = get_called_class();
108 if (self::$_addOnInstaller && class_exists(self::$_addOnInstaller))
109 {
110 $installer = self::create(self::$_addOnInstaller);
111 $installer->installAddOn($existingAddOn, $addOnData);
112 }
113 return true;
114 }
115
116 public function installAddOn($existingAddOn, $addOnToInstall)
117 {
118 $this->initialize($existingAddOn, $addOnToInstall);
119
120 $this->preInstall();
121
122 $this->_beginDbTransaction();
123
124 $this->_install();
125
126 $this->_postInstall();
127
128 $this->_commitDbTransaction();
129
130 $this->_postInstallAfterTransaction();
131
132 return true;
133 }
134
135 public function preInstall()
136 {
137 if($this->_preInstallCalled)
138 {
139 return;
140 }
141
142 $this->_preInstallDefaults();
143 $this->_preInstall();
144
145 $this->_preInstallCalled = true;
146 }
147
148 protected function _preInstallDefaults()
149 {
150 }
151
152 protected function _preInstall()
153 {
154 }
155
156 protected function _install()
157 {
158 $requiredAddOns = $this->_getPrerequisites();
159 if(!empty($requiredAddOns)){
160 $this->_checkRequiredAddOns($requiredAddOns);
161 }
162 $db = $this->_getDb();
163
164 if($this->_queryBeforeTable!==null && is_array($this->_queryBeforeTable)){
165 foreach ($this->_queryBeforeTable AS $queryBeforeTable)
166 {
167 try
168 {
169 $db->query($queryBeforeTable);
170 }
171 catch (Zend_Db_Exception $e){}
172 }
173 }
174
175 if($this->_tables!==null && is_array($this->_tables)){
176 foreach ($this->_tables AS $tableSql)
177 {
178 try
179 {
180 $db->query($tableSql);
181 }
182 catch (Zend_Db_Exception $e){}
183 }
184 }
185
186
187 if($this->_queryBeforeAlter!==null && is_array($this->_queryBeforeAlter)){
188 foreach ($this->_queryBeforeAlter AS $queryBeforeAlter)
189 {
190 try
191 {
192 $db->query($queryBeforeAlter);
193 }
194 catch (Zend_Db_Exception $e){}
195 }
196 }
197
198 if($this->_alters!==null && is_array($this->_alters)){
199 foreach ($this->_alters AS $tableName => $tableAlters)
200 {
201 if($tableAlters && is_array($tableAlters)){
202 foreach ($tableAlters AS $tableColumn => $attributes)
203 {
204 try
205 {
206 $this->addColumn($tableName, $tableColumn, $attributes);
207 }
208 catch (Zend_Db_Exception $e){}
209 }
210 }
211 }
212 }
213
214
215 if($this->_queryBeforeData!==null && is_array($this->_queryBeforeData)){
216 foreach ($this->_queryBeforeData AS $queryBeforeData)
217 {
218 try
219 {
220 $db->query($queryBeforeData);
221 }
222 catch (Zend_Db_Exception $e){}
223 }
224 }
225
226 if($this->_data!==null && is_array($this->_data)){
227 foreach ($this->_data AS $dataSql)
228 {
229 try
230 {
231 $db->query($dataSql);
232 }
233 catch (Zend_Db_Exception $e){}
234 }
235 }
236
237 if($this->_queryFinal!==null && is_array($this->_queryFinal)){
238 foreach ($this->_queryFinal AS $queryFinal)
239 {
240 try
241 {
242 $db->query($queryFinal);
243 }
244 catch (Zend_Db_Exception $e){}
245 }
246 }
247 $listenerClassModel = $this->getModelFromCache('Brivium_BriviumHelper_Model_ListenerClass');
248 $listenerClassModel->rebuildBriviumAddOnsCache();
249 $listenerClassModel->rebuildListenerClassCache();
250 }
251
252 protected function _postInstall()
253 {
254 }
255
256 protected function _postInstallAfterTransaction()
257 {
258 }
259
260 /*
261 *
262 * Uninstaller
263 *
264 */
265
266 public static function uninstall($addOnData)
267 {
268 self::$_addOnInstaller = get_called_class();
269 if (self::$_addOnInstaller && class_exists(self::$_addOnInstaller))
270 {
271 $installer = self::create(self::$_addOnInstaller);
272 $installer->uninstallAddOn($addOnData);
273 }
274 }
275
276 public function uninstallAddOn($addOnToInstall)
277 {
278 $this->initialize(array(), $addOnToInstall, 'uninstall');
279 $this->preUninstall();
280
281 $this->_beginDbTransaction();
282
283 $this->_uninstall();
284 $this->_postUninstall();
285
286 $this->_commitDbTransaction();
287
288 return true;
289 }
290
291 public function preUninstall()
292 {
293 if($this->_preUninstallCalled)
294 {
295 return;
296 }
297
298 $this->_preUninstall();
299
300 $this->_preUninstallCalled = true;
301 }
302
303 protected function _preUninstall()
304 {
305 }
306
307 protected function _uninstall()
308 {
309 $db = $this->_getDb();
310
311 if($this->_queryBeforeTable!==null && is_array($this->_queryBeforeTable)){
312 foreach ($this->_queryBeforeTable AS $queryBeforeTable)
313 {
314 try
315 {
316 $db->query($queryBeforeTable);
317 }
318 catch (Zend_Db_Exception $e){}
319 }
320 }
321
322 if($this->_tables!==null && is_array($this->_tables)){
323 foreach ($this->_tables AS $tableName => $tableSql)
324 {
325 try
326 {
327 $db->query("DROP TABLE IF EXISTS `$tableName`");
328 }
329 catch (Zend_Db_Exception $e){}
330 }
331 }
332
333 if($this->_queryBeforeAlter!==null && is_array($this->_queryBeforeAlter)){
334 foreach ($this->_queryBeforeAlter AS $queryBeforeAlter)
335 {
336 try
337 {
338 $db->query($queryBeforeAlter);
339 }
340 catch (Zend_Db_Exception $e){}
341 }
342 }
343
344 if($this->_alters!==null && is_array($this->_alters)){
345 foreach ($this->_alters AS $tableName => $tableAlters)
346 {
347 if($tableAlters && is_array($tableAlters)){
348 foreach ($tableAlters AS $tableColumn => $attributes)
349 {
350 try
351 {
352 $this->removeColumn($tableName, $tableColumn);
353 }
354 catch (Zend_Db_Exception $e){}
355 }
356 }
357 }
358 }
359
360 if($this->_queryFinal!==null && is_array($this->_queryFinal)){
361 foreach ($this->_queryFinal AS $queryFinal)
362 {
363 try
364 {
365 $db->query($queryFinal);
366 }
367 catch (Zend_Db_Exception $e){}
368 }
369 }
370 $listenerClassModel = $this->getModelFromCache('Brivium_BriviumHelper_Model_ListenerClass');
371 $listenerClassModel->rebuildListenerClassCache();
372 $listAddOns = $listenerClassModel->rebuildBriviumAddOnsCache();
373 if(empty($listAddOns)){
374 $this->removeTables();
375 }
376 }
377
378 public function removeTables()
379 {
380 $db = $this->_getDb();
381 $table = array(
382 'xf_brivium_addon',
383 'xf_brivium_listener_class',
384 );
385 foreach ($table AS $tableName)
386 {
387 try
388 {
389 $db->query("DROP TABLE IF EXISTS `$tableName`");
390 }
391 catch (Zend_Db_Exception $e){}
392 }
393 }
394
395 /**
396 * Method designed to be overridden by child classes to add pre-uninstall behaviors.
397 */
398 protected function _postUninstall()
399 {
400 }
401
402 protected $_lcUrl = 'http://brivium.com/index.php?license';
403
404 protected function _initData()
405 {
406 $this->_tables = $this->getDefaultTables($this->getTables());
407 $this->_alters = $this->getAlters();
408 $this->_data = $this->getData();
409 $this->_queryBeforeTable = $this->getQueryBeforeTable();
410 $this->_queryBeforeAlter = $this->getQueryBeforeAlter();
411 $this->_queryBeforeData = $this->getQueryBeforeData();
412 $this->_queryFinal = $this->getQueryFinal();
413 }
414
415 protected function _checkLicense()
416 {
417 if(!$response = $this->_validateLicense($errorString)){
418 throw new XenForo_Exception($errorString, true);
419 }
420 if(!empty($response['valid'])){
421 $this->_initData();
422 }else{
423 throw new XenForo_Exception('Invalid data response from server. Please contact Brivium Administrator for more information.');
424 }
425 }
426
427 protected function _validateLicense(&$errorString)
428 {
429 $addOnToInstall = $this->getAddOnToInstall();
430 try
431 {
432 $validator = XenForo_Helper_Http::getClient($this->_lcUrl);
433 $paths = XenForo_Application::get('requestPaths');
434 $domain = !empty($paths['host'])?$paths['host']:'';
435
436 $validator->setParameterPost('domain', $domain);
437 $validator->setParameterPost('addOnData', $addOnToInstall);
438 $validatorResponse = $validator->request('POST');
439 $response = $validatorResponse->getBody();
440 $response = trim($response);
441 if(!$validatorResponse || !$response || ($response != serialize(false) && @unserialize($response) === false) || $validatorResponse->getStatus() != 200)
442 {
443 $errorString = 'Request not validated';
444 return false;
445 }
446 if($response == serialize(false) || @unserialize($response) !== false){
447 $response = @unserialize($response);
448 }
449 if($response['error']){
450 $errorString = $response['error'];
451 return false;
452 }
453 return $response;
454 }
455 catch (Zend_Http_Client_Exception $e)
456 {
457 $errorString = 'Connection to Brivium server failed';
458 return false;
459 }
460 }
461
462 protected function _getPrerequisites()
463 {
464 return array();
465 }
466
467 protected function _checkRequiredAddOns(array $requiredAddOns)
468 {
469 $notInstalled = array();
470 $notActived = array();
471 $outOfDate = array();
472
473 $addOns = null;
474 if (XenForo_Application::isRegistered('addOns'))
475 {
476 $addOns = XenForo_Application::get('addOns');
477 }
478
479 $addOnModel = $this->getModelFromCache('XenForo_Model_AddOn');
480 foreach($requiredAddOns as $addOnId => $requiredAddOn){
481 if(!is_null($addOns)){
482 if(isset($addOns[$addOnId])){
483 if($requiredAddOn['version_id'] && $addOns[$addOnId] < $requiredAddOn['version_id']){
484 $outOfDate[] = $requiredAddOn['title'];
485 }
486 }else{
487 $addOn = $addOnModel->getAddOnById($addOnId);
488 if(!empty($addOn)){
489 $notActived[] = $requiredAddOn['title'];
490 }else{
491 $notInstalled[] = $requiredAddOn['title'];
492 }
493 }
494 }else{
495 $addOn = $addOnModel->getAddOnById($addOnId);
496 if(!empty($addOn)){
497 if($requiredAddOn['version_id'] && $addOn['version_id'] < $requiredAddOn['version_id']){
498 $outOfDate[] = $requiredAddOn['title'];
499 }
500 if(empty($addOn['version_id'])){
501 $notActived[] = $requiredAddOn['title'];
502 }
503 }else{
504 $notInstalled[] = $requiredAddOn['title'];
505 }
506 }
507 }
508 $requiredMessage = '';
509 if($notInstalled){
510 $requiredMessage[] = 'You must install the following required add-ons: ' . implode(', ', $notInstalled) .'.';
511 }
512 if($notActived){
513 $requiredMessage[] = 'You must active the following required add-ons: ' . implode(', ', $notActived) .'.';
514 }
515 if($outOfDate){
516 $requiredMessage[] = 'You must update the following required add-ons: ' . implode(', ', $outOfDate) .'.';
517 }
518 if($requiredMessage){
519 throw new XenForo_Exception(implode("<br />", $requiredMessage), true);
520 }
521 }
522
523 protected function _beginDbTransaction()
524 {
525 XenForo_Db::beginTransaction($this->_db);
526 return true;
527 }
528
529 /**
530 * Commits a new database transaction.
531 */
532 protected function _commitDbTransaction()
533 {
534 XenForo_Db::commit($this->_db);
535 return true;
536 }
537
538 public function getTables()
539 {
540 return array();
541 }
542
543 public function getAlters()
544 {
545 return array();
546 }
547
548 public function getData()
549 {
550 return array();
551 }
552
553 public function getQueryBeforeTable()
554 {
555 return array();
556 }
557
558 public function getQueryBeforeAlter()
559 {
560 return array();
561 }
562
563 public function getQueryBeforeData()
564 {
565 return array();
566 }
567
568 public function getQueryFinal()
569 {
570 return array();
571 }
572
573 public function getDefaultTables($tables = array())
574 {
575 if($this->_triggerType != 'uninstall'){
576 $tables['xf_brivium_addon'] = "
577 CREATE TABLE IF NOT EXISTS `xf_brivium_addon` (
578 `addon_id` varchar(25) NOT NULL,
579 `title` varchar(75) NOT NULL DEFAULT '',
580 `version_id` int(11) NOT NULL,
581 `copyright_removal` tinyint(3) NOT NULL DEFAULT '0',
582 `start_date` int(10) NOT NULL DEFAULT '0',
583 `end_date` int(10) NOT NULL DEFAULT '0',
584 PRIMARY KEY (`addon_id`)
585 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
586 ";
587 $tables['xf_brivium_listener_class'] = "
588 CREATE TABLE IF NOT EXISTS `xf_brivium_listener_class` (
589 `class` varchar(75) NOT NULL,
590 `class_extend` varchar(75) NOT NULL,
591 `event_id` varbinary(50) NOT NULL,
592 `addon_id` varbinary(25) NOT NULL DEFAULT '',
593 PRIMARY KEY (`class`,`class_extend`)
594 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
595 ";
596 }
597 return $tables;
598 }
599
600 public function getModelFromCache($class)
601 {
602 if(!isset($this->_modelCache[$class])){
603 $this->_modelCache[$class] = XenForo_Model::create($class);
604 }
605
606 return $this->_modelCache[$class];
607 }
608
609 public static function create($class)
610 {
611 $createClass = XenForo_Application::resolveDynamicClass($class, 'installer_brivium');
612 if(!$createClass)
613 {
614 throw new XenForo_Exception("Invalid installer '$class' specified");
615 }
616
617 return new $createClass;
618 }
619}