PageRenderTime 53ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/default_www/frontend/core/engine/model.php

https://github.com/Lesso/forkcms
PHP | 493 lines | 215 code | 91 blank | 187 comment | 42 complexity | fb595e36e8493aebdce01669f1fcd3cb MD5 | raw file
  1. <?php
  2. /**
  3. * In this file we store all generic functions that we will be using in the frontend.
  4. *
  5. * @package frontend
  6. * @subpackage core
  7. *
  8. * @author Tijs Verkoyen <tijs@netlash.com>
  9. * @since 2.0
  10. */
  11. class FrontendModel
  12. {
  13. /**
  14. * cached module-settings
  15. *
  16. * @var array
  17. */
  18. private static $moduleSettings = array();
  19. /**
  20. * Add a number to the string
  21. *
  22. * @return string
  23. * @param string $string The string where the number will be appended to.
  24. */
  25. public static function addNumber($string)
  26. {
  27. // split
  28. $chunks = explode('-', $string);
  29. // count the chunks
  30. $count = count($chunks);
  31. // get last chunk
  32. $last = $chunks[$count - 1];
  33. // is nummeric
  34. if(SpoonFilter::isNumeric($last))
  35. {
  36. // remove last chunk
  37. array_pop($chunks);
  38. // join together, and increment the last one
  39. $string = implode('-', $chunks ) . '-' . ((int) $last + 1);
  40. }
  41. // not numeric, so add -2
  42. else $string .= '-2';
  43. // return
  44. return $string;
  45. }
  46. /**
  47. * Add parameters to an URL
  48. *
  49. * @return string
  50. * @param string $URL The URL to append the parameters too.
  51. * @param array $parameters The parameters as key-value-pairs.
  52. */
  53. public static function addURLParameters($URL, array $parameters)
  54. {
  55. // redefine
  56. $URL = (string) $URL;
  57. // no parameters means no appending
  58. if(empty($parameters)) return $URL;
  59. // split to remove the hash
  60. $chunks = explode('#', $URL, 2);
  61. // init var
  62. $hash = '';
  63. if(isset($chunks[1]))
  64. {
  65. // reset URL
  66. $URL = $chunks[0];
  67. // store has
  68. $hash = '#' . $chunks[1];
  69. }
  70. // build querystring
  71. $queryString = http_build_query($parameters, null, '&amp;');
  72. // already GET parameters?
  73. if(mb_strpos($URL, '?') !== false) return $URL .= '&' . $queryString . $hash;
  74. // no GET-parameters defined before
  75. else return $URL .= '?' . $queryString . $hash;
  76. }
  77. /**
  78. * Generate a totally random but readable/speakable password
  79. *
  80. * @return string
  81. * @param int[optional] $length The maximum length for the password to generate.
  82. * @param bool[optional] $uppercaseAllowed Are uppercase letters allowed?
  83. * @param bool[optional] $lowercaseAllowed Are lowercase letters allowed?
  84. */
  85. public static function generatePassword($length = 6, $uppercaseAllowed = true, $lowercaseAllowed = true)
  86. {
  87. // list of allowed vowels and vowelsounds
  88. $vowels = array('a', 'e', 'i', 'u', 'ae', 'ea');
  89. // list of allowed consonants and consonant sounds
  90. $consonants = array('b', 'c', 'd', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'r', 's', 't', 'u', 'v', 'w', 'tr', 'cr', 'fr', 'dr', 'wr', 'pr', 'th', 'ch', 'ph', 'st');
  91. // init vars
  92. $consonantsCount = count($consonants);
  93. $vowelsCount = count($vowels);
  94. $pass = '';
  95. $tmp = '';
  96. // create temporary pass
  97. for($i = 0; $i < $length; $i++) $tmp .= ($consonants[rand(0, $consonantsCount - 1)] . $vowels[rand(0, $vowelsCount - 1)]);
  98. // reformat the pass
  99. for($i = 0; $i < $length; $i++)
  100. {
  101. if(rand(0, 1) == 1) $pass .= strtoupper(substr($tmp, $i, 1));
  102. else $pass .= substr($tmp, $i, 1);
  103. }
  104. // reformat it again, if uppercase isn't allowed
  105. if(!$uppercaseAllowed) $pass = strtolower($pass);
  106. // reformat it again, if uppercase isn't allowed
  107. if(!$lowercaseAllowed) $pass = strtoupper($pass);
  108. // return pass
  109. return $pass;
  110. }
  111. /**
  112. * Get (or create and get) a database-connection
  113. * @later split the write and read connection
  114. *
  115. * @return SpoonDatabase
  116. * @param bool[optional] $write Do you want the write-connection or not?
  117. */
  118. public static function getDB($write = false)
  119. {
  120. // redefine
  121. $write = (bool) $write;
  122. // do we have a db-object ready?
  123. if(!Spoon::exists('database'))
  124. {
  125. // create instance
  126. $db = new SpoonDatabase(DB_TYPE, DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE, DB_PORT);
  127. // utf8 compliance & MySQL-timezone
  128. $db->execute('SET CHARACTER SET utf8, NAMES utf8, time_zone = "+0:00"');
  129. // store
  130. Spoon::set('database', $db);
  131. }
  132. // return db-object
  133. return Spoon::get('database');
  134. }
  135. /**
  136. * Get a module setting
  137. *
  138. * @return mixed
  139. * @param string $module The module wherefor a setting has to be retrieved.
  140. * @param string $name The name of the setting to be retrieved.
  141. * @param mixed[optional] $defaultValue A value that will be stored if the setting isn't present.
  142. */
  143. public static function getModuleSetting($module, $name, $defaultValue = null)
  144. {
  145. // redefine
  146. $module = (string) $module;
  147. $name = (string) $name;
  148. // get them all
  149. if(empty(self::$moduleSettings))
  150. {
  151. // fetch settings
  152. $settings = (array) self::getDB()->getRecords('SELECT ms.module, ms.name, ms.value
  153. FROM modules_settings AS ms
  154. INNER JOIN modules AS m ON ms.module = m.name
  155. WHERE m.active = ?',
  156. array('Y'));
  157. // loop settings and cache them, also unserialize the values
  158. foreach($settings as $row) self::$moduleSettings[$row['module']][$row['name']] = unserialize($row['value']);
  159. }
  160. // if the setting doesn't exists, store it (it will be available from te cache)
  161. if(!isset(self::$moduleSettings[$module][$name])) self::setModuleSetting($module, $name, $defaultValue);
  162. // return
  163. return self::$moduleSettings[$module][$name];
  164. }
  165. /**
  166. * Get all module settings at once
  167. *
  168. * @return array
  169. * @param string $module The module wherefor all settings has to be retrieved.
  170. */
  171. public static function getModuleSettings($module)
  172. {
  173. // redefine
  174. $module = (string) $module;
  175. // get them all
  176. if(empty(self::$moduleSettings[$module]))
  177. {
  178. // fetch settings
  179. $settings = (array) self::getDB()->getRecords('SELECT ms.module, ms.name, ms.value
  180. FROM modules_settings AS ms');
  181. // loop settings and cache them, also unserialize the values
  182. foreach($settings as $row) self::$moduleSettings[$row['module']][$row['name']] = unserialize($row['value']);
  183. }
  184. // validate again
  185. if(!isset(self::$moduleSettings[$module])) return array();
  186. // return
  187. return self::$moduleSettings[$module];
  188. }
  189. /**
  190. * Get all data for a page
  191. *
  192. * @return array
  193. * @param int $pageId The pageId wherefor the data will be retrieved.
  194. */
  195. public static function getPage($pageId)
  196. {
  197. // redefine
  198. $pageId = (int) $pageId;
  199. // get database instance
  200. $db = self::getDB();
  201. // get data
  202. $record = (array) $db->getRecord('SELECT p.id, p.revision_id, p.template_id, p.title, p.navigation_title, p.navigation_title_overwrite, p.data,
  203. m.title AS meta_title, m.title_overwrite AS meta_title_overwrite,
  204. m.keywords AS meta_keywords, m.keywords_overwrite AS meta_keywords_overwrite,
  205. m.description AS meta_description, m.description_overwrite AS meta_description_overwrite,
  206. m.custom AS meta_custom,
  207. m.url, m.url_overwrite,
  208. t.path AS template_path, t.data as template_data
  209. FROM pages AS p
  210. INNER JOIN meta AS m ON p.meta_id = m.id
  211. INNER JOIN pages_templates AS t ON p.template_id = t.id
  212. WHERE p.id = ? AND p.status = ? AND p.hidden = ? AND p.language = ?
  213. LIMIT 1',
  214. array($pageId, 'active', 'N', FRONTEND_LANGUAGE));
  215. // validate
  216. if(empty($record)) return array();
  217. // unserialize page data and template data
  218. if(isset($record['data']) && $record['data'] != '') $record['data'] = unserialize($record['data']);
  219. if(isset($record['template_data']) && $record['template_data'] != '') $record['template_data'] = @unserialize($record['template_data']);
  220. // get blocks
  221. $record['blocks'] = (array) $db->getRecords('SELECT pb.extra_id, pb.html,
  222. pe.module AS extra_module, pe.type AS extra_type, pe.action AS extra_action, pe.data AS extra_data
  223. FROM pages_blocks AS pb
  224. LEFT OUTER JOIN pages_extras AS pe ON pb.extra_id = pe.id
  225. WHERE pb.revision_id = ? AND pb.status = ?
  226. ORDER BY pb.id',
  227. array($record['revision_id'], 'active'));
  228. // loop blocks
  229. foreach($record['blocks'] as $index => $row)
  230. {
  231. // unserialize data if it is available
  232. if(isset($row['data'])) $record['blocks'][$index]['data'] = unserialize($row['data']);
  233. }
  234. // return page record
  235. return $record;
  236. }
  237. /**
  238. * Get the UTC date in a specific format. Use this method when inserting dates in the database!
  239. *
  240. * @return string
  241. * @param string[optional] $format The format wherin the data will be returned, if not provided we will return it in MySQL-datetime-format.
  242. * @param int[optional] $timestamp A UNIX-timestamp that will be used as base.
  243. */
  244. public static function getUTCDate($format = null, $timestamp = null)
  245. {
  246. // init var
  247. $format = ($format !== null) ? (string) $format : 'Y-m-d H:i:s';
  248. // no timestamp given
  249. if($timestamp === null) return gmdate($format);
  250. // timestamp given
  251. return gmdate($format, (int) $timestamp);
  252. }
  253. /**
  254. * General method to check if something is spam
  255. *
  256. * @return bool
  257. * @param string $content The content that was submitted.
  258. * @param string $permaLink The permanent location of the entry the comment was submitted to.
  259. * @param string[optional] $author Commenters name.
  260. * @param string[optional] $email Commenters email address.
  261. * @param string[optional] $URL Commenters URL.
  262. * @param string[optional] $type May be blank, comment, trackback, pingback, or a made up value like "registration".
  263. */
  264. public static function isSpam($content, $permaLink, $author = null, $email = null, $URL = null, $type = 'comment')
  265. {
  266. // get some settings
  267. $akismetKey = self::getModuleSetting('core', 'akismet_key');
  268. // invalid key, so we can't detect spam
  269. if($akismetKey === '') return false;
  270. // require the class
  271. require_once PATH_LIBRARY . '/external/akismet.php';
  272. // create new instance
  273. $akismet = new Akismet($akismetKey, SITE_URL);
  274. // set properties
  275. $akismet->setTimeOut(10);
  276. $akismet->setUserAgent('Fork CMS/2.1');
  277. // try it to decide if the item is spam
  278. try
  279. {
  280. // check with Akismet if the item is spam
  281. return $akismet->isSpam($content, $author, $email, $URL, $permaLink, $type);
  282. }
  283. // catch exceptions
  284. catch(Exception $e)
  285. {
  286. // in debug mode we want to see exceptions, otherwise the fallback will be triggered
  287. if(SPOON_DEBUG) throw $e;
  288. }
  289. // when everything fails
  290. return false;
  291. }
  292. /**
  293. * Push a notification to Apple's notifications-server
  294. *
  295. * @return void
  296. * @param mixed $alert The message/dictonary to send.
  297. * @param int[optional] $badge The number for the badge.
  298. * @param string[optional] $sound The sound that should be played.
  299. * @param array[optional] $extraDictionaries Extra dictionaries.
  300. */
  301. public static function pushToAppleApp($alert, $badge = null, $sound = null, array $extraDictionaries = null)
  302. {
  303. // get ForkAPI-keys
  304. $publicKey = FrontendModel::getModuleSetting('core', 'fork_api_public_key', '');
  305. $privateKey = FrontendModel::getModuleSetting('core', 'fork_api_private_key', '');
  306. // validate keys
  307. if($publicKey != '' && $privateKey != '')
  308. {
  309. // get all apple-device tokens
  310. $deviceTokens = (array) FrontendModel::getDB()->getColumn('SELECT s.value
  311. FROM users AS i
  312. INNER JOIN users_settings AS s
  313. WHERE i.active = ? AND i.deleted = ? AND s.name = ? AND s.value != ?',
  314. array('Y', 'N', 'apple_device_token', 'N;'));
  315. // any devices?
  316. if(!empty($deviceTokens))
  317. {
  318. // init var
  319. $tokens = array();
  320. // loop devices
  321. foreach($deviceTokens as $row)
  322. {
  323. // unserialize
  324. $row = unserialize($row);
  325. // loop and add
  326. foreach($row as $item) $tokens[] = $item;
  327. }
  328. // any tokens?
  329. if(!empty($tokens))
  330. {
  331. // require the class
  332. require_once PATH_LIBRARY . '/external/fork_api.php';
  333. // create instance
  334. $forkAPI = new ForkAPI($publicKey, $privateKey);
  335. try
  336. {
  337. // push
  338. $response = $forkAPI->applePush($tokens, $alert, $badge, $sound, $extraDictionaries);
  339. if(!empty($response))
  340. {
  341. // get db
  342. $db = FrontendModel::getDB(true);
  343. // loop the failed keys and remove them
  344. foreach($response as $deviceToken)
  345. {
  346. // get setting wherin the token is available
  347. $row = $db->getRecord('SELECT i.*
  348. FROM users_settings AS i
  349. WHERE i.name = ? AND i.value LIKE ?',
  350. array('apple_device_token', '%' . $deviceToken . '%'));
  351. // any rows?
  352. if(!empty($row))
  353. {
  354. // reset data
  355. $data = unserialize($row['value']);
  356. // loop keys
  357. foreach($data as $key => $token)
  358. {
  359. // match and unset if needed.
  360. if($token == $deviceToken) unset($data[$key]);
  361. }
  362. // no more tokens left?
  363. if(empty($data)) $db->delete('users_settings', 'user_id = ? AND name = ?', array($row['user_id'], $row['name']));
  364. // save
  365. else $db->update('users_settings', array('value' => serialize($data)), 'user_id = ? AND name = ?', array($row['user_id'], $row['name']));
  366. }
  367. }
  368. }
  369. }
  370. // catch exceptions
  371. catch(Exception $e)
  372. {
  373. if(SPOON_DEBUG) throw $e;
  374. }
  375. }
  376. }
  377. }
  378. }
  379. /**
  380. * Store a modulesetting
  381. *
  382. * @return void
  383. * @param string $module The module wherefor a setting has to be stored.
  384. * @param string $name The name of the setting.
  385. * @param mixed $value The value (will be serialized so make sure the type is correct).
  386. */
  387. public static function setModuleSetting($module, $name, $value)
  388. {
  389. // redefine
  390. $module = (string) $module;
  391. $name = (string) $name;
  392. $value = serialize($value);
  393. // store
  394. self::getDB(true)->execute('INSERT INTO modules_settings (module, name, value)
  395. VALUES (?, ?, ?)
  396. ON DUPLICATE KEY UPDATE value = ?',
  397. array($module, $name, $value, $value));
  398. // store in cache
  399. self::$moduleSettings[$module][$name] = unserialize($value);
  400. }
  401. }
  402. ?>