PageRenderTime 68ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/src/backend/PartKeepr/PartKeepr.php

https://github.com/scrupeus/PartKeepr
PHP | 469 lines | 272 code | 80 blank | 117 comment | 40 complexity | ab3008485434dec4f8d9dbae73150741 MD5 | raw file
Possible License(s): GPL-3.0, CC-BY-3.0, LGPL-2.1
  1. <?php
  2. namespace PartKeepr;
  3. use Doctrine\Common\ClassLoader,
  4. PartKeepr\SystemNotice\SystemNoticeManager,
  5. Doctrine\ORM\Configuration,
  6. Doctrine\ORM\EntityManager,
  7. PartKeepr\Util\Configuration as PartKeeprConfiguration;
  8. class PartKeepr {
  9. /**
  10. *
  11. * Contains the doctrine entity manager.
  12. * @var Doctrine\ORM\EntityManager
  13. */
  14. private static $entityManager = null;
  15. /**
  16. * Initializes the PartKeepr system
  17. *
  18. * You *need* to call this method before doing anything else.
  19. *
  20. * An environment is used to load a different configuration file.
  21. * Usually, you don't need to pass anything here.
  22. *
  23. * @param $environment string The environment to use, null otherwise.
  24. * @return nothing
  25. */
  26. public static function initialize ($environment = null) {
  27. self::initializeClassLoaders();
  28. self::initializeConfig($environment);
  29. self::initializeDoctrine();
  30. }
  31. /**
  32. * Initializes the doctrine class loader and sets up the
  33. * directories.
  34. *
  35. * @param none
  36. * @return nothing
  37. */
  38. public static function initializeClassLoaders() {
  39. require_once 'Doctrine/Common/ClassLoader.php';
  40. $classLoader = new ClassLoader('PartKeepr', self::getRootDirectory() . "/src/backend");
  41. $classLoader->register();
  42. $classLoader = new ClassLoader('Doctrine\ORM');
  43. $classLoader->register();
  44. $classLoader = new ClassLoader("Doctrine\DBAL\Migrations", self::getRootDirectory() ."/3rdparty/doctrine-migrations/lib");
  45. $classLoader->register();
  46. $classLoader = new ClassLoader('Doctrine\DBAL');
  47. $classLoader->register();
  48. $classLoader = new ClassLoader('Doctrine\Common');
  49. $classLoader->register();
  50. $classLoader = new ClassLoader('Symfony', 'Doctrine');
  51. $classLoader->register();
  52. $classLoader = new ClassLoader("DoctrineExtensions\NestedSet", self::getRootDirectory() ."/3rdparty/doctrine2-nestedset/lib");
  53. $classLoader->register();
  54. }
  55. /**
  56. * Returns an array of all cronjobs which are required for proper execution of PartKeepr.
  57. *
  58. * @return Array The filenames of each cronjob which is required
  59. */
  60. public static function getRequiredCronjobs () {
  61. return array(
  62. "CreateStatisticSnapshot.php",
  63. "UpdatePartCacheData.php",
  64. "UpdateTipsOfTheDay.php",
  65. "CheckForUpdates.php"
  66. );
  67. }
  68. /**
  69. * Initializes the configuration for a given environment.
  70. *
  71. * An environment is used to load a different configuration file.
  72. *
  73. * Usually, you don't need to pass anything here.
  74. *
  75. *
  76. * @param $environment string The environment to use, null otherwise.
  77. * @return nothing
  78. */
  79. public static function initializeConfig ($environment = null) {
  80. if ($environment != null) {
  81. $config = self::getRootDirectory()."/config-$environment.php";
  82. } else {
  83. $config = self::getRootDirectory()."/config.php";
  84. }
  85. if (file_exists($config)) {
  86. include($config);
  87. }
  88. // Check if the files path is set. If not, fall back to <partkeepr-root>/data/
  89. if (PartKeeprConfiguration::getOption("partkeepr.files.path", null) === null) {
  90. PartKeeprConfiguration::setOption("partkeepr.files.path",
  91. PartKeepr::getRootDirectory() . "/data/");
  92. }
  93. // Check if the image path is set. If not, fall back to <configured-files-directory>/images/
  94. if (PartKeeprConfiguration::getOption("partkeepr.images.path", null) === null) {
  95. PartKeeprConfiguration::setOption("partkeepr.images.path",
  96. PartKeeprConfiguration::getOption("partkeepr.files.path") . "images/");
  97. }
  98. // Check if the image cache path is set. If not, fall back to <configured-images-directory>/images/
  99. if (PartKeeprConfiguration::getOption("partkeepr.images.cache", null) === null) {
  100. PartKeeprConfiguration::setOption("partkeepr.images.cache",
  101. PartKeeprConfiguration::getOption("partkeepr.images.path") . "cache/");
  102. }
  103. }
  104. /**
  105. * Checks against the versions at partkeepr.org.
  106. *
  107. * If a newer version was found, create a system notice entry.
  108. */
  109. public static function doVersionCheck () {
  110. $data = file_get_contents("http://www.partkeepr.org/versions.json");
  111. $versions = json_decode($data, true);
  112. if (PartKeeprVersion::PARTKEEPR_VERSION == "{V_GIT}") { return; }
  113. if (substr(PartKeeprVersion::PARTKEEPR_VERSION,0,17) == "partkeepr-nightly") { return; }
  114. if (version_compare(PartKeepr::getVersion(), $versions[0]["version"], '<')) {
  115. SystemNoticeManager::getInstance()->createUniqueSystemNotice(
  116. "PARTKEEPR_VERSION_".$versions[0]["version"],
  117. sprintf(PartKeepr::i18n("New PartKeepr Version %s available"), $versions[0]["version"]),
  118. sprintf(PartKeepr::i18n("PartKeepr Version %s changelog:"), $versions[0]["version"]) . "\n\n".
  119. $versions[0]["changelog"]
  120. );
  121. }
  122. }
  123. /**
  124. * Initializes the doctrine framework and
  125. * sets all required configuration options.
  126. *
  127. * @param none
  128. * @return nothing
  129. */
  130. public static function initializeDoctrine () {
  131. $config = new Configuration;
  132. $driverImpl = $config->newDefaultAnnotationDriver(
  133. array(__DIR__)
  134. );
  135. $config->setMetadataDriverImpl($driverImpl);
  136. $connectionOptions = PartKeepr::createConnectionOptionsFromConfig();
  137. switch (strtolower(PartKeeprConfiguration::getOption("partkeepr.cache.implementation", "default"))) {
  138. case "apc":
  139. $cache = new \Doctrine\Common\Cache\ApcCache();
  140. break;
  141. case "xcache":
  142. if (php_sapi_name() !== "cli") {
  143. $cache = new \Doctrine\Common\Cache\XcacheCache();
  144. } else {
  145. // For CLI SAPIs, revert to the ArrayCache as Xcache spits out strange warnings when running in CLI.
  146. $cache = new \Doctrine\Common\Cache\ArrayCache();
  147. }
  148. break;
  149. case "memcache":
  150. $memcache = new \Memcache();
  151. $memcache->connect( PartKeeprConfiguration::getOption("partkeepr.cache.memcache.host", "localhost"),
  152. PartKeeprConfiguration::getOption("partkeepr.cache.memcache.port", "11211"));
  153. $cache = new \Doctrine\Common\Cache\MemcacheCache();
  154. $cache->setMemcache($memcache);
  155. break;
  156. case "default":
  157. case "auto":
  158. if (extension_loaded("xcache")) {
  159. $cache = new \Doctrine\Common\Cache\XcacheCache();
  160. } else if (extension_loaded("apc")) {
  161. $cache = new \Doctrine\Common\Cache\ApcCache();
  162. } else {
  163. $cache = new \Doctrine\Common\Cache\ArrayCache();
  164. }
  165. break;
  166. case "none":
  167. $cache = new \Doctrine\Common\Cache\ArrayCache();
  168. break;
  169. }
  170. $config->setMetadataCacheImpl($cache);
  171. $config->setQueryCacheImpl($cache);
  172. $config->setProxyDir(self::getRootDirectory() . '/data/proxies');
  173. $config->setProxyNamespace('Proxies');
  174. $config->setEntityNamespaces(self::getEntityClasses());
  175. $config->setAutoGenerateProxyClasses(false);
  176. if (PartKeeprConfiguration::getOption("partkeepr.database.echo_sql_log", false) === true) {
  177. $logger = new \Doctrine\DBAL\Logging\EchoSQLLogger();
  178. $config->setSQLLogger($logger);
  179. }
  180. self::$entityManager = EntityManager::create($connectionOptions, $config);
  181. }
  182. public static function createConnectionOptionsFromConfig () {
  183. $connectionOptions = array();
  184. $driver = PartKeeprConfiguration::getOption("partkeepr.database.driver");
  185. switch ($driver) {
  186. case "pdo_mysql":
  187. // Force SET NAMES, as PHP/PDO <5.3.6 silently ignores "charset"
  188. $connectionOptions["driverOptions"] = array(1002=>'SET NAMES utf8');
  189. case "pdo_pgsql":
  190. case "pdo_oci":
  191. case "oci8":
  192. case "pdo_sqlsrv":
  193. $connectionOptions["driver"] = $driver;
  194. $connectionOptions["dbname"] = PartKeeprConfiguration::getOption("partkeepr.database.dbname", "partkeepr");
  195. $connectionOptions["user"] = PartKeeprConfiguration::getOption("partkeepr.database.username", "partkeepr");
  196. $connectionOptions["password"] = PartKeeprConfiguration::getOption("partkeepr.database.password", "partkeepr");
  197. $connectionOptions["charset"] = "utf8";
  198. /**
  199. * Compatibility with older configuration files. We check for the key "hostname" as well as "host".
  200. */
  201. if (PartKeeprConfiguration::getOption("partkeepr.database.hostname", null) !== null) {
  202. $connectionOptions["host"] = PartKeeprConfiguration::getOption("partkeepr.database.hostname");
  203. } else {
  204. $connectionOptions["host"] = PartKeeprConfiguration::getOption("partkeepr.database.host", "localhost");
  205. }
  206. if (PartKeeprConfiguration::getOption("partkeepr.database.port") !== null) {
  207. $connectionOptions["port"] = PartKeeprConfiguration::getOption("partkeepr.database.port");
  208. }
  209. if (PartKeeprConfiguration::getOption("partkeepr.database.mysql_socket", null) !== null) {
  210. $connectionOptions["unix_socket"] = PartKeeprConfiguration::getOption("partkeepr.database.mysql_socket");
  211. }
  212. break;
  213. case "pdo_sqlite":
  214. $connectionOptions["driver"] = $driver;
  215. $connectionOptions["user"] = PartKeeprConfiguration::getOption("partkeepr.database.username", "partkeepr");
  216. $connectionOptions["password"] = PartKeeprConfiguration::getOption("partkeepr.database.password", "partkeepr");
  217. $connectionOptions["path"] = PartKeeprConfiguration::getOption("partkeepr.database.sqlite_path", PartKeepr::getRootDirectory() . "/data/partkeepr.sqlite");
  218. break;
  219. default:
  220. throw new \Exception(sprintf("Unknown driver %s", $driver));
  221. }
  222. return $connectionOptions;
  223. }
  224. /**
  225. * Returns the EntityManager. Shortcut for getEntityManager().
  226. * @return \Doctrine\ORM\EntityManager The EntityManager
  227. */
  228. public static function getEM () {
  229. return self::getEntityManager();
  230. }
  231. public static function getRootDirectory () {
  232. return dirname(dirname(dirname(__DIR__)));
  233. }
  234. /**
  235. * Returns the EntityManager.
  236. * @return Doctrine\ORM\EntityManager The EntityManager
  237. */
  238. public static function getEntityManager () {
  239. if (!self::$entityManager instanceof EntityManager) {
  240. throw new \Exception("No EntityManager found. Make sure you called initializeDoctrine() or initialize().");
  241. }
  242. return self::$entityManager;
  243. }
  244. /**
  245. * Returns the class metadata for all entity classes
  246. * @return array an array of class metadata objects
  247. */
  248. public static function getClassMetaData () {
  249. $classes = self::getEntityClasses();
  250. $aClasses = array();
  251. foreach ($classes as $class) {
  252. $aClasses[] = PartKeepr::getEM()->getClassMetadata($class);
  253. }
  254. return $aClasses;
  255. }
  256. /**
  257. * Returns a list of all classes we use for entities.
  258. * @return array An array of strings with all class names
  259. */
  260. public static function getEntityClasses () {
  261. return array(
  262. 'PartKeepr\User\User',
  263. 'PartKeepr\Session\Session',
  264. 'PartKeepr\Footprint\Footprint',
  265. 'PartKeepr\Footprint\FootprintImage',
  266. 'PartKeepr\Footprint\FootprintAttachment',
  267. 'PartKeepr\FootprintCategory\FootprintCategory',
  268. 'PartKeepr\Part\Part',
  269. 'PartKeepr\Part\PartUnit',
  270. 'PartKeepr\Part\PartManufacturer',
  271. 'PartKeepr\Part\PartDistributor',
  272. 'PartKeepr\Part\PartImage',
  273. 'PartKeepr\Part\PartAttachment',
  274. 'PartKeepr\PartCategory\PartCategory',
  275. 'PartKeepr\Project\Project',
  276. 'PartKeepr\Project\ProjectPart',
  277. 'PartKeepr\Project\ProjectAttachment',
  278. 'PartKeepr\StorageLocation\StorageLocation',
  279. 'PartKeepr\StorageLocation\StorageLocationImage',
  280. 'PartKeepr\Stock\StockEntry',
  281. 'PartKeepr\Manufacturer\Manufacturer',
  282. 'PartKeepr\Manufacturer\ManufacturerICLogo',
  283. 'PartKeepr\Distributor\Distributor',
  284. 'PartKeepr\Image\Image',
  285. 'PartKeepr\Image\CachedImage',
  286. 'PartKeepr\TempImage\TempImage',
  287. 'PartKeepr\UploadedFile\TempUploadedFile',
  288. 'PartKeepr\Statistic\StatisticSnapshot',
  289. 'PartKeepr\Statistic\StatisticSnapshotUnit',
  290. 'PartKeepr\SiPrefix\SiPrefix',
  291. 'PartKeepr\Unit\Unit',
  292. 'PartKeepr\PartParameter\PartParameter',
  293. 'PartKeepr\TipOfTheDay\TipOfTheDay',
  294. 'PartKeepr\TipOfTheDay\TipOfTheDayHistory',
  295. 'PartKeepr\UserPreference\UserPreference',
  296. 'PartKeepr\SystemNotice\SystemNotice',
  297. 'PartKeepr\CronLogger\CronLogger'
  298. );
  299. }
  300. /**
  301. * Formats a message and applies internationalization.
  302. *
  303. * This method accepts sprintf-like parameters, which are appended after the $string parameter.
  304. *
  305. * @param $string string The string to internationalize
  306. * @todo stub
  307. */
  308. public static function i18n ($string) {
  309. if (func_num_args() > 1) {
  310. $args = func_get_args();
  311. array_shift($args);
  312. return vsprintf($string, $args);
  313. } else {
  314. return $string;
  315. }
  316. }
  317. /**
  318. * Returns a new GUID.
  319. * @return string The new GUID
  320. */
  321. public static function createGUIDv4() {
  322. return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
  323. // 32 bits for "time_low"
  324. mt_rand(0, 0xffff), mt_rand(0, 0xffff),
  325. // 16 bits for "time_mid"
  326. mt_rand(0, 0xffff),
  327. // 16 bits for "time_hi_and_version",
  328. // four most significant bits holds version number 4
  329. mt_rand(0, 0x0fff) | 0x4000,
  330. // 16 bits, 8 bits for "clk_seq_hi_res",
  331. // 8 bits for "clk_seq_low",
  332. // two most significant bits holds zero and one for variant DCE1.1
  333. mt_rand(0, 0x3fff) | 0x8000,
  334. // 48 bits for "node"
  335. mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
  336. );
  337. }
  338. /**
  339. * Returns the current PartKeepr version.
  340. * @return string The PartKeepr Version
  341. */
  342. public static function getVersion () {
  343. if (PartKeeprVersion::PARTKEEPR_VERSION == "{V_GIT}") {
  344. return "GIT development version";
  345. }
  346. return PartKeeprVersion::PARTKEEPR_VERSION;
  347. }
  348. /**
  349. * This is a re-implementation of gettype().
  350. *
  351. * The PHP documentation states that the "gettype" return values will change in the future, so we need
  352. * to make sure we don't get bitten by the change.
  353. *
  354. * @param mixed $var
  355. * @return string The type
  356. */
  357. public static function getType($var)
  358. {
  359. if (is_array($var)) return "array";
  360. if (is_bool($var)) return "boolean";
  361. if (is_float($var)) return "float";
  362. if (is_int($var)) return "integer";
  363. if (is_null($var)) return "NULL";
  364. if (is_numeric($var)) return "numeric";
  365. if (is_object($var)) return "object";
  366. if (is_resource($var)) return "resource";
  367. if (is_string($var)) return "string";
  368. return "unknown type";
  369. }
  370. /**
  371. * Returns the effective size from a human-readable byte format.
  372. *
  373. * Example:
  374. * getBytesFromHumanReadable("1M") will return 1048576.
  375. *
  376. * @param string $size_str The byte
  377. * @return int The bytes
  378. */
  379. public static function getBytesFromHumanReadable ($size_str)
  380. {
  381. switch (substr ($size_str, -1))
  382. {
  383. case 'M': case 'm': return (int)$size_str * 1048576;
  384. case 'K': case 'k': return (int)$size_str * 1024;
  385. case 'G': case 'g': return (int)$size_str * 1073741824;
  386. default: return $size_str;
  387. }
  388. }
  389. }