PageRenderTime 69ms CodeModel.GetById 40ms RepoModel.GetById 0ms app.codeStats 0ms

/src/libraries/controllers/SetupController.php

https://github.com/rhaphazard/frontend
PHP | 430 lines | 323 code | 48 blank | 59 comment | 72 complexity | 04968ccd141ad7169c6812254b45076c MD5 | raw file
  1. <?php
  2. /**
  3. * Setup controller for HTML endpoints
  4. * This controls the setup flow when the software is first installed.
  5. * The main purpose of this flow is to generate settings.ini.
  6. *
  7. * @author Jaisen Mathai <jaisen@jmathai.com>
  8. * @author Kevin Hornschemeier <khornschemeier@gmail.com>
  9. */
  10. class SetupController
  11. {
  12. /**
  13. * Returns the setup step 1 screen markup.
  14. *
  15. * @return string HTML
  16. */
  17. public static function setup()
  18. {
  19. $step = 1;
  20. $appId = 'openphoto-frontend';
  21. getSession('step', 1);
  22. $imageLibs = array();
  23. if(class_exists('Imagick'))
  24. $imageLibs['ImageMagick'] = 'ImageMagick';
  25. if(class_exists('Gmagick'))
  26. $imageLibs['GraphicsMagick'] = 'GraphicsMagick';
  27. if(extension_loaded('gd') && function_exists('gd_info'))
  28. $imageLibs['GD'] = 'GD';
  29. $errors = self::verifyRequirements($imageLibs);
  30. if(count($errors) > 0)
  31. $step = 0;
  32. else
  33. $errors = '';
  34. $body = getTheme()->get('setup.php', array('imageLibs' => $imageLibs, 'appId' => $appId, 'step' => $step, 'errors' => $errors));
  35. getTheme()->display('template.php', array('body' => $body, 'page' => 'setup'));
  36. }
  37. /**
  38. * Posts the setup values from step 1 of the form, checks them, and saves in session
  39. *
  40. * @return void HTTP redirect (setup step 2)
  41. */
  42. public static function setupPost()
  43. {
  44. $step = 1;
  45. $appId = isset($_POST['appId']) ? $_POST['appId'] : '';
  46. $email = isset($_POST['email']) ? $_POST['email'] : '';
  47. $input = array(
  48. array('Email', $email, 'required')
  49. );
  50. $errors = getForm()->hasErrors($input);
  51. if($errors === false)
  52. {
  53. getSession()->set('step', 2);
  54. getSession()->set('appId', $appId);
  55. getSession()->set('email', $email);
  56. getRoute()->redirect('/setup/2');
  57. }
  58. $body = getTheme()->get('setup.php', array('emai' => $email, 'appId' => $appId, 'step' => $step, 'errors' => $errors));
  59. getTheme()->display('template.php', array('body' => $body, 'page' => 'setup'));
  60. }
  61. /**
  62. * Returns the setup step 2 screen markup.
  63. *
  64. * @return string HTML
  65. */
  66. public static function setup2()
  67. {
  68. // make sure the user should be on this step
  69. if(getSession()->get('step') != 2)
  70. getRoute()->redirect('/setup');
  71. $step = 2;
  72. $imageLibs = array();
  73. if(class_exists('Imagick'))
  74. $imageLibs['ImageMagick'] = 'ImageMagick';
  75. if(class_exists('Gmagick'))
  76. $imageLibs['GraphicsMagick'] = 'GraphicsMagick';
  77. if(extension_loaded('gd') && function_exists('gd_info'))
  78. $imageLibs['GD'] = 'GD';
  79. $body = getTheme()->get('setup.php', array('imageLibs' => $imageLibs, 'appId' => 'openphoto-frontend', 'step' => $step));
  80. getTheme()->display('template.php', array('body' => $body, 'page' => 'setup'));
  81. }
  82. /**
  83. * Posts the setup values from step 2 of the form, checks them, and saves in session
  84. *
  85. * @return void HTTP redirect (setup step 3)
  86. */
  87. public static function setup2Post()
  88. {
  89. getSession()->set('step', 3);
  90. getSession()->set('imageLibrary', $_POST['imageLibrary']);
  91. getSession()->set('database', $_POST['database']);
  92. getSession()->set('fileSystem', $_POST['fileSystem']);
  93. getRoute()->redirect('/setup/3');
  94. }
  95. /**
  96. * Returns the setup step 3 screen markup.
  97. *
  98. * @return string HTML
  99. */
  100. public static function setup3()
  101. {
  102. // make sure the user should be on this step
  103. if(getSession()->get('step') != 3)
  104. {
  105. if(getSession()->get('step') == 2)
  106. getRoute()->redirect('/setup/2');
  107. getRoute()->redirect('/setup');
  108. }
  109. $step = 3;
  110. $appId = getSession()->get('appId');
  111. $usesAws = (getSession()->get('database') == 'SimpleDb' || getSession()->get('fileSystem') == 'S3') ? true : false;
  112. $usesMySql = (getSession()->get('database') == 'MySql') ? true : false;
  113. $usesLocalFs = (getSession()->get('fileSystem') == 'LocalFs') ? true : false;
  114. $usesS3 = (getSession()->get('fileSystem') == 'S3') ? true : false;
  115. $usesSimpleDb = (getSession()->get('database') == 'SimpleDb') ? true : false;
  116. $body = getTheme()->get('setup.php', array('step' => $step, 'usesAws' => $usesAws, 'usesMySql' => $usesMySql, 'usesLocalFs' => $usesLocalFs, 'usesS3' => $usesS3, 'usesSimpleDb' => $usesSimpleDb, 'appId' => $appId));
  117. getTheme()->display('template.php', array('body' => $body, 'page' => 'setup'));
  118. }
  119. /**
  120. * Posts the setup values from step 3 of the form, checks them, and saves in session
  121. *
  122. * @return void HTTP redirect (home)
  123. */
  124. public static function setup3Post()
  125. {
  126. $step = 3;
  127. $appId = getSession()->get('appId');
  128. $usesAws = (getSession()->get('database') == 'SimpleDb' || getSession()->get('fileSystem') == 'S3') ? true : false;
  129. $usesMySql = (getSession()->get('database') == 'MySql') ? true : false;
  130. $usesLocalFs = (getSession()->get('fileSystem') == 'LocalFs') ? true : false;
  131. $usesS3 = (getSession()->get('fileSystem') == 'S3') ? true : false;
  132. $usesSimpleDb = (getSession()->get('database') == 'SimpleDb') ? true : false;
  133. $awsErrors = false;
  134. $mySqlErrors = false;
  135. $localFsErrors = false;
  136. $fsErrors = false;
  137. $dbErrors = false;
  138. $writeErrors = false;
  139. if($usesAws)
  140. {
  141. $awsKey = $_POST['awsKey'];
  142. $awsSecret = $_POST['awsSecret'];
  143. $input = array(
  144. array('Amazon Access Key ID', $awsKey, 'required'),
  145. array('Amazon Secret Access Key', $awsSecret, 'required')
  146. );
  147. if($usesS3)
  148. {
  149. $s3Bucket = $_POST['s3Bucket'];
  150. $input[] = array('Amazon S3 Bucket Name', $s3Bucket, 'required');
  151. }
  152. if($usesSimpleDb)
  153. {
  154. $simpleDbDomain = $_POST['simpleDbDomain'];
  155. $input[] = array('Amazon SimpleDb Domain', $simpleDbDomain, 'required');
  156. }
  157. $awsErrors = getForm()->hasErrors($input);
  158. }
  159. if($usesMySql)
  160. {
  161. $mySqlHost = $_POST['mySqlHost'];
  162. $mySqlUser = $_POST['mySqlUser'];
  163. $mySqlPassword = $_POST['mySqlPassword'];
  164. $mySqlDb = $_POST['mySqlDb'];
  165. $mySqlTablePrefix = $_POST['mySqlTablePrefix'];
  166. $input = array(
  167. array('MySQL Host', $mySqlHost, 'required'),
  168. array('MySQL Username', $mySqlUser, 'required'),
  169. array('MySQL Password', $mySqlPassword, 'required'),
  170. array('MySQL Database', $mySqlDb, 'required'),
  171. array('MySQL Table Prefix', $mySqlTablePrefix, 'required')
  172. );
  173. $mySqlErrors = getForm()->hasErrors($input);
  174. }
  175. if($usesLocalFs)
  176. {
  177. $fsRoot = $_POST['fsRoot'];
  178. $fsHost = $_POST['fsHost'];
  179. $input = array(
  180. array('File System Root', $fsRoot, 'required'),
  181. array('File System Host', $fsHost, 'required')
  182. );
  183. $localFsErrors = getForm()->hasErrors($input);
  184. }
  185. if($awsErrors === false && $mySqlErrors === false && $localFsErrors === false)
  186. {
  187. $credentials = new stdClass;
  188. if($usesAws)
  189. {
  190. getSession()->set('awsKey', $awsKey);
  191. getSession()->set('awsSecret', $awsSecret);
  192. $credentials->awsKey = $awsKey;
  193. $credentials->awsSecret = $awsSecret;
  194. $aws = new stdClass;
  195. if($usesS3)
  196. {
  197. getSession()->set('s3BucketName', $s3Bucket);
  198. $aws->s3BucketName = $s3Bucket;
  199. $aws->s3Host = "{$s3Bucket}.s3.amazonaws.com";
  200. }
  201. if($usesSimpleDb)
  202. {
  203. getSession()->set('simpleDbDomain', $simpleDbDomain);
  204. $aws->simpleDbDomain = $simpleDbDomain;
  205. }
  206. }
  207. if($usesMySql)
  208. {
  209. getSession()->set('mySqlHost', $mySqlHost);
  210. getSession()->set('mySqlUser', $mySqlUser);
  211. getSession()->set('mySqlPassword', $mySqlPassword);
  212. getSession()->set('mySqlDb', $mySqlDb);
  213. getSession()->set('mySqlTablePrefix', $mySqlTablePrefix);
  214. $mysql = new stdClass;
  215. $mysql->mySqlHost = $mySqlHost;
  216. $mysql->mySqlUser = $mySqlUser;
  217. $mysql->mySqlPassword = $mySqlPassword;
  218. $mysql->mySqlDb = $mySqlDb;
  219. $mysql->mySqlTablePrefix = $mySqlTablePrefix;
  220. }
  221. if($usesLocalFs)
  222. {
  223. getSession()->set('fsRoot', $fsRoot);
  224. getSession()->set('fsHost', $fsHost);
  225. $fs = new stdClass;
  226. $fs->fsRoot = $fsRoot;
  227. $fs->fsHost = $fsHost;
  228. }
  229. $systems = new stdClass;
  230. $systems->database = getSession()->get('database');
  231. $systems->fileSystem = getSession()->get('fileSystem');
  232. // save the config info
  233. getConfig()->set('credentials', $credentials);
  234. if($usesAws)
  235. getConfig()->set('aws', $aws);
  236. if($usesMySql)
  237. getConfig()->set('mysql', $mysql);
  238. if($usesLocalFs)
  239. getConfig()->set('localfs', $fs);
  240. getConfig()->set('systems', $systems);
  241. $fsObj = getFs();
  242. $dbObj = getDb();
  243. $user = exec("whoami");
  244. if(!$fsObj->initialize())
  245. {
  246. if($usesAws)
  247. $fsErrors[] = 'We were unable to initialize your S3 bucket.<ul><li>Make sure you\'re <a href="http://aws.amazon.com/s3/">signed up for AWS S3</a>.</li><li>Double check your AWS credentials.</li><li>S3 bucket names are globally unique, make sure yours isn\'t already in use by someone else.</li><li>S3 bucket names can\'t have certain special characters. Try using just alpha-numeric characters and periods.</li></ul>';
  248. else if($usesLocalFs)
  249. $fsErrors[] = "We were unable to set up your local file system using <em>{$fs->rsRoot}</em>. Make sure that the following user has proper permissions ({$user}).";
  250. else
  251. $fsErrors[] = 'An unknown error occurred while setting up your file system. Check your error logs to see if there\'s more information about the error.';
  252. }
  253. if(!$dbObj->initialize())
  254. {
  255. if($usesAws)
  256. $dbErrors[] = 'We were unable to initialize your SimpleDb domains.<ul><li>Make sure you\'re <a href="http://aws.amazon.com/simpledb/">signed up for AWS SimpleDb</a>.</li><li>Double check your AWS credentials.</li><li>SimpleDb domains cannot contain special characters such as periods.</li></ul>';
  257. else if($usesMySql)
  258. $dbErrors[] = 'We were unable to properly connect to your MySql database server. Please verify that the host, username and password are correct and have proper permissions to create a database.';
  259. else
  260. $dbErrors[] = 'An unknown error occurred while setting up your file system. Check your error logsto see if there\'s more information about the error.';
  261. }
  262. if($fsErrors === false && $dbErrors === false)
  263. {
  264. $writeError = self::writeConfigFile();
  265. if($writeErrors === false)
  266. getRoute()->redirect('/?m=welcome');
  267. else
  268. $writeErrors[] = "We were unable to save your settings file. Please make sure that the following user has proper permissions to write to src/configs ({$user}).";
  269. }
  270. }
  271. // combine all errors if they exist
  272. $errors = array();
  273. if(is_array($awsErrors))
  274. $errors = array_merge($errors, $awsErrors);
  275. if(is_array($mySqlErrors))
  276. $errors = array_merge($errors, $mySqlErrors);
  277. if(is_array($localFsErrors))
  278. $errors = array_merge($errors, $localFsErrors);
  279. if(is_array($fsErrors))
  280. $errors = array_merge($errors, $fsErrors);
  281. if(is_array($dbErrors))
  282. $errors = array_merge($errors, $dbErrors);
  283. if(is_array($writeErrors))
  284. $errors = array_merge($errors, $writeErrors);
  285. $body = getTheme()->get('setup.php', array('step' => $step, 'usesAws' => $usesAws, 'usesMySql' => $usesMySql, 'usesLocalFs' => $usesLocalFs, 'usesS3' => $usesS3, 'usesSimpleDb' => $usesSimpleDb, 's3Bucket' => $s3Bucket, 'simpleDbDomain' => $simpleDbDomain, 'appId' => $appId, 'errors' => $errors));
  286. getTheme()->display('template.php', array('body' => $body, 'page' => 'setup'));
  287. }
  288. /**
  289. * Clears out the session data and redirects to step 1
  290. *
  291. * @return void HTTP redirect (setup step 1)
  292. */
  293. public static function setupRestart()
  294. {
  295. getSession()->end();
  296. getRoute()->redirect('/setup');
  297. }
  298. /**
  299. * Verify the server requirements are available on this host.
  300. *
  301. * @return mixed TRUE on success, array on error
  302. */
  303. private static function verifyRequirements($imageLibs)
  304. {
  305. $errors = array();
  306. $configDir = dirname(dirname(dirname(__FILE__))) . '/configs';
  307. $generatedDir = "{$configDir}/generated";
  308. if(file_exists($generatedDir) && is_writable($generatedDir) && !empty($imageLibs))
  309. # No errors, return empty array
  310. return $errors;
  311. $user = exec("whoami");
  312. if(empty($user))
  313. $user = 'Apache user';
  314. if(!is_writable($configDir))
  315. $errors[] = "Insufficient privileges to complete setup.<ul><li>Make sure the user <em>{$user}</em> can write to <em>{$configDir}</em>.</li></ul>";
  316. if(!file_exists($generatedDir))
  317. {
  318. $createDir = mkdir($generatedDir, 0700);
  319. if(!$createDir)
  320. $errors[] = "Could not create configuration directory.<ul><li>Make sure the user <um>{$user}</em> can write to <em>{$generatedDir}</em>.</li></ul>";
  321. }
  322. elseif(!is_writable($generatedDir))
  323. {
  324. $errors[] = "Directory exist but is not writable.<ul><li>Make sure the user <um>{$user}</em> can write to <em>{$generatedDir}</em>.</li></ul>";
  325. }
  326. if(empty($imageLibs))
  327. $errors[] = 'No suitable image library exists.<ul><li>Make sure that one of the following are installed: <em><a href="http://php.net/imagick">Imagick</a></em>, <em><a href="http://php.net/gmagick">Gmagick</a></em>, or <em><a href="http://php.net/gd">GD</a></em>.</li></ul>';
  328. return $errors;
  329. }
  330. /**
  331. * Write out the settings config file
  332. *
  333. * @return boolean TRUE on success, FALSE on error
  334. */
  335. private static function writeConfigFile()
  336. {
  337. // continue if no errors
  338. $baseDir = dirname(dirname(dirname(__FILE__)));
  339. $htmlDir = "{$baseDir}/html";
  340. $libDir = "{$baseDir}/libraries";
  341. $configDir = "{$baseDir}/configs";
  342. $replacements = array(
  343. '{adapters}' => "{$libDir}/adapters",
  344. '{configs}' => $configDir,
  345. '{controllers}' => "{$libDir}/controllers",
  346. '{external}' => "{$libDir}/external",
  347. '{libraries}' => "{$libDir}",
  348. '{models}' => "{$libDir}/models",
  349. '{photos}' => "{$htmlDir}/photos",
  350. '{themes}' => "{$htmlDir}/assets/themes",
  351. '{exiftran}' => exec('which exiftran'),
  352. '{localSecret}' => sha1(uniqid(true)),
  353. '{awsKey}' => "",
  354. '{awsSecret}' => "",
  355. '{s3Bucket}' => getSession()->get('s3BucketName'),
  356. '{s3Host}' => getSession()->get('s3BucketName') . '.s3.amazonaws.com',
  357. '{simpleDbDomain}' => "",
  358. '{mySqlHost}' => "",
  359. '{mySqlUser}' => "",
  360. '{mySqlPassword}' => "",
  361. '{mySqlDb}' => "",
  362. '{mySqlTablePrefix}' => "",
  363. '{fsRoot}' => "",
  364. '{fsHost}' => "",
  365. '{email}' => getSession()->get('email')
  366. );
  367. $pReplace = array();
  368. $session = getSession()->getAll();
  369. foreach($session as $key => $val)
  370. $pReplace["{{$key}}"] = $val;
  371. $replacements = array_merge($replacements, $pReplace);
  372. $generatedIni = str_replace(
  373. array_keys($replacements),
  374. array_values($replacements),
  375. file_get_contents("{$configDir}/template.ini")
  376. );
  377. $iniWritten = file_put_contents(sprintf("%s/generated/%s.ini", $configDir, getenv('HTTP_HOST')), $generatedIni);
  378. if(!$iniWritten)
  379. return false;
  380. return true;
  381. }
  382. }