PageRenderTime 75ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 1ms

/inc/core.php

https://github.com/barszczmm/wp-lifestream
PHP | 2842 lines | 2361 code | 259 blank | 222 comment | 266 complexity | 530e52da5c382667f08ee59ee3761549 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. if (!class_exists('SimplePie'))
  3. {
  4. require_once(LIFESTREAM_PATH . '/lib/simplepie.inc.php');
  5. }
  6. global $wpdb, $userdata, $lifestream;
  7. function lifestream_path_join()
  8. {
  9. $bits = func_get_args();
  10. $sep = (in_array(PHP_OS, array("WIN32", "WINNT")) ? '\\' : '/');
  11. foreach ($bits as $key=>$value) {
  12. $bits[$key] = rtrim($value, $sep);
  13. }
  14. return implode($sep, $bits);
  15. }
  16. function lifestream_array_key_pop($array, $key, $default=null)
  17. {
  18. $value = @$array[$key];
  19. unset($array[$key]);
  20. if (!$value) $value = $default;
  21. return $value;
  22. }
  23. // Returns the utf string corresponding to the unicode value (from php.net, courtesy - romans@void.lv)
  24. function lifestream_code2utf($num)
  25. {
  26. if ($num < 128) return chr($num);
  27. if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
  28. if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
  29. if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
  30. return '';
  31. }
  32. function lifestream_str_startswith($string, $chunk)
  33. {
  34. return substr($string, 0, strlen($chunk)) == $chunk;
  35. }
  36. function lifestream_str_endswith($string, $chunk)
  37. {
  38. return substr($string, strlen($chunk)*-1) == $chunk;
  39. }
  40. function lifestream_get_class_constant($class, $const)
  41. {
  42. return constant(sprintf('%s::%s', $class, $const));
  43. }
  44. class Lifestream_Error extends Exception { }
  45. class Lifestream_ValidationError extends Exception { }
  46. class Lifestream_FeedFetchError extends Lifestream_Error { }
  47. class Lifestream_Event
  48. {
  49. /**
  50. * Represents a single event in the database.
  51. */
  52. function __construct(&$lifestream, $row)
  53. {
  54. $this->lifestream = $lifestream;
  55. $this->date = $row->timestamp;
  56. $this->data = array(unserialize($row->data));
  57. $this->id = $row->id;
  58. $this->timestamp = $row->timestamp;
  59. $this->total = 1;
  60. $this->is_grouped = false;
  61. $this->key = $row->key;
  62. $this->owner = $row->owner;
  63. $this->owner_id = $row->owner_id;
  64. $this->visible = $row->visible;
  65. $this->link = @(!empty($this->data['link']) ? $this->data['link'] : $row->link);
  66. $cls = $this->lifestream->get_feed($row->feed);
  67. $this->feed = new $cls($this->lifestream, unserialize($row->options), $row->feed_id);
  68. }
  69. function __toString()
  70. {
  71. return $this->data[0]['title'];
  72. }
  73. function get_event_display()
  74. {
  75. return $this->feed->get_event_display($this, $this->data[0]);
  76. }
  77. function get_event_link()
  78. {
  79. return $this->feed->get_event_link($this, $this->data[0]);
  80. }
  81. function get_timesince()
  82. {
  83. return $this->lifestream->timesince($this->timestamp);
  84. }
  85. function get_date()
  86. {
  87. return $this->date + LIFESTREAM_DATE_OFFSET;
  88. }
  89. /**
  90. * Returns an HTML-ready string.
  91. */
  92. function render($options=array())
  93. {
  94. return $this->feed->render($this, $options);
  95. }
  96. function get_label_instance($options=array())
  97. {
  98. if (!isset($this->_label_instance))
  99. {
  100. $this->_label_instance = $this->feed->get_label($this, $options);
  101. }
  102. return $this->_label_instance;
  103. }
  104. function get_label($options=array())
  105. {
  106. $label_inst = $this->get_label_instance($options);
  107. if (count($this->data) > 1)
  108. {
  109. if (@$options['show_owners'] || $this->lifestream->get_option('show_owners'))
  110. {
  111. $label = $label_inst->get_label_plural_user();
  112. }
  113. else
  114. {
  115. $label = $label_inst->get_label_plural();
  116. }
  117. }
  118. else
  119. {
  120. if (@$options['show_owners'] || $this->lifestream->get_option('show_owners'))
  121. {
  122. $label = $label_inst->get_label_single_user();
  123. }
  124. else
  125. {
  126. $label = $label_inst->get_label_single();
  127. }
  128. }
  129. return $label;
  130. }
  131. function get_feed_label($options=array())
  132. {
  133. $label_inst = $this->get_label_instance($options);
  134. return $label_inst->get_feed_label();
  135. }
  136. function get_url()
  137. {
  138. if (count($this->data) > 1)
  139. {
  140. // return the public url if it's grouped
  141. $url = $this->feed->get_public_url();
  142. if ($url) return $url;
  143. }
  144. else
  145. {
  146. $url = $this->data[0]['link'];
  147. if ($url) return $url;
  148. }
  149. return '#';
  150. }
  151. }
  152. class Lifestream_EventGroup extends Lifestream_Event
  153. {
  154. /**
  155. * Represents a grouped event in the database.
  156. */
  157. function __construct(&$lifestream, $row)
  158. {
  159. parent::__construct($lifestream, $row);
  160. $this->total = $row->total ? $row->total : 1;
  161. $this->data = unserialize($row->data);
  162. $this->is_grouped = true;
  163. }
  164. function get_event_display($bit)
  165. {
  166. return $this->feed->get_event_display($this, $bit);
  167. }
  168. function get_event_link($bit)
  169. {
  170. return $this->feed->get_event_link($this, $bit);
  171. }
  172. }
  173. class Lifestream
  174. {
  175. // stores all registered feeds
  176. public $feeds = array();
  177. // stores file locations to feed classes
  178. public $paths = array();
  179. // stores theme information
  180. public $themes = array();
  181. // stores icon folder names
  182. public $icons = array();
  183. // current theme
  184. public $theme = 'default';
  185. protected $paging_key = 'ls_p';
  186. protected $valid_image_types = array('image/gif' => 'gif',
  187. 'image/jpeg' => 'jpeg',
  188. 'image/png' => 'png',
  189. 'image/gif' => 'gif',
  190. 'image/x-icon' => 'ico',
  191. 'image/bmp' => 'bmp',
  192. 'image/vnd.microsoft.icon' => 'ico'
  193. );
  194. protected $valid_image_extensions = array(
  195. 'gif', 'jpg', 'jpeg', 'gif', 'png', 'ico'
  196. );
  197. function html_entity_decode($string)
  198. {
  199. static $trans_tbl;
  200. // replace numeric entities
  201. $string = preg_replace('~&#x([0-9a-f]+);~ei', 'lifestream_code2utf(hexdec("\\1"))', $string);
  202. $string = preg_replace('~&#([0-9]+);~e', 'lifestream_code2utf(\\1)', $string);
  203. // replace literal entities
  204. if (!isset($trans_tbl))
  205. {
  206. $trans_tbl = array();
  207. foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key)
  208. $trans_tbl[$key] = utf8_encode($val);
  209. }
  210. return strtr($string, $trans_tbl);
  211. }
  212. // function html_entity_decode($string)
  213. // {
  214. // $string = html_entity_decode($string, ENT_QUOTES, 'utf-8');
  215. //
  216. // $string = preg_replace('~&#x0*([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string);
  217. // $string = preg_replace('~&#0*([0-9]+);~e', 'chr(\\1)', $string);
  218. //
  219. // return $string;
  220. // }
  221. function parse_nfo_file($file)
  222. {
  223. $data = array();
  224. if (!is_file($file)) return $data;
  225. $fp = file($file);
  226. foreach ($fp as $line)
  227. {
  228. if (lifestream_str_startswith('#', $line)) continue;
  229. list($key, $value) = explode(':', $line, 2);
  230. $data[strtolower($key)] = trim($value);
  231. }
  232. return $data;
  233. }
  234. function get_icon_paths()
  235. {
  236. $directories = array(
  237. lifestream_path_join(LIFESTREAM_PATH, 'icons')
  238. );
  239. if ($this->get_option('icon_dir') && $this->get_option('icon_dir') != $directories[0]) {
  240. $directories[] = $this->get_option('icon_dir');
  241. }
  242. return $directories;
  243. }
  244. function get_rss_feed_url()
  245. {
  246. $permalink = get_option('permalink_structure');
  247. if (!empty($permalink))
  248. {
  249. $url = trailingslashit(get_bloginfo('rss2_url')) . 'lifestream-feed';
  250. }
  251. else {
  252. $url = trailingslashit(get_bloginfo('url')) . 'wp-rss2.php?feed=lifestream-feed';
  253. }
  254. return $url;
  255. }
  256. /**
  257. * Find each icons/name/generic.png file.
  258. */
  259. function detect_icons()
  260. {
  261. $directories = $this->get_icon_paths();
  262. foreach ($directories as $base_dir)
  263. {
  264. if (!is_dir($base_dir)) continue;
  265. $handler = opendir($base_dir);
  266. while ($file = readdir($handler))
  267. {
  268. // ignore hidden files
  269. if (lifestream_str_startswith($file, '.')) continue;
  270. // if its not a directory we dont care
  271. $path = lifestream_path_join($base_dir, $file);
  272. if (!is_dir($path)) continue;
  273. $ext_file = lifestream_path_join($path, 'generic.png');
  274. if (is_file($ext_file))
  275. {
  276. $data = $this->parse_nfo_file(lifestream_path_join($path, 'icons.txt'));
  277. if (!$data['name']) $data['name'] = $file;
  278. $data['__path'] = $path;
  279. $data['__url'] =
  280. $this->icons[$file] = $data;
  281. }
  282. }
  283. }
  284. }
  285. function get_extension_paths()
  286. {
  287. $directories = array(
  288. lifestream_path_join(LIFESTREAM_PATH, 'extensions')
  289. );
  290. if ($this->get_option('extension_dir') && $this->get_option('extension_dir') != $directories[0]) {
  291. $directories[] = $this->get_option('extension_dir');
  292. }
  293. return $directories;
  294. }
  295. /**
  296. * Find each extension/name/extension.inc.php file.
  297. */
  298. function detect_extensions()
  299. {
  300. $lifestream =& $this;
  301. $directories = $this->get_extension_paths();
  302. foreach ($directories as $base_dir)
  303. {
  304. if (!is_dir($base_dir)) continue;
  305. $handler = opendir($base_dir);
  306. while ($file = readdir($handler))
  307. {
  308. // ignore hidden files
  309. if (lifestream_str_startswith($file, '.')) continue;
  310. $path = lifestream_path_join($base_dir, $file);
  311. // if its not a directory we dont care
  312. if (!is_dir($path)) continue;
  313. // check for extension.inc.php
  314. $ext_file = lifestream_path_join($path, 'extension.inc.php');
  315. if (is_file($ext_file))
  316. {
  317. include($ext_file);
  318. }
  319. }
  320. }
  321. }
  322. function get_theme_paths()
  323. {
  324. $directories = array(
  325. lifestream_path_join(LIFESTREAM_PATH, 'themes')
  326. );
  327. if ($this->get_option('theme_dir') && $this->get_option('theme_dir') != $directories[0]) {
  328. $directories[] = $this->get_option('theme_dir');
  329. }
  330. return $directories;
  331. }
  332. /**
  333. * Find each themes/name/theme.txt file.
  334. */
  335. function detect_themes()
  336. {
  337. $directories = $this->get_theme_paths();
  338. foreach ($directories as $base_dir)
  339. {
  340. if (!is_dir($base_dir)) continue;
  341. $handler = opendir($base_dir);
  342. while ($file = readdir($handler))
  343. {
  344. // ignore hidden files
  345. if (lifestream_str_startswith($file, '.')) continue;
  346. // if its not a directory we dont care
  347. $path = lifestream_path_join($base_dir, $file);
  348. if (!is_dir($path)) continue;
  349. // check for main.inc.php
  350. $ext_file = lifestream_path_join($path, 'theme.txt');
  351. if (is_file($ext_file))
  352. {
  353. $theme = array();
  354. $theme = $this->parse_nfo_file($ext_file);
  355. $theme['__path'] = $path;
  356. if (!array_key_exists('name', $theme)) continue;
  357. $this->themes[$file] = $theme;
  358. }
  359. }
  360. }
  361. }
  362. function get_media_url_for_icon($filename='generic.png', $iconpack='default')
  363. {
  364. $path = lifestream_path_join($this->icons[$iconpack]['__path'], $filename);
  365. if (!is_file($path))
  366. {
  367. $filename = 'generic.png';
  368. $path = lifestream_path_join(LIFESTREAM_PATH, 'icons', 'default', $filename);
  369. }
  370. return $this->get_absolute_media_url($path);
  371. }
  372. function get_icon_media_url($filename)
  373. {
  374. return $this->get_media_url_for_icon($filename, $this->get_option('icons', 'default'));
  375. }
  376. function get_theme_media_url($filename)
  377. {
  378. return $this->get_media_url_for_theme($filename, $this->get_option('theme', 'default'));
  379. }
  380. function get_media_url_for_theme($filename, $theme='default')
  381. {
  382. // base dir is now $theme['__path'] so we must abstract the web dir
  383. $path = lifestream_path_join($this->themes[$theme]['__path'], 'media', $filename);
  384. if (!is_file($path))
  385. {
  386. $path = lifestream_path_join(LIFESTREAM_PATH, 'themes', 'default', 'media', $filename);
  387. }
  388. return $this->get_absolute_media_url($path);
  389. }
  390. function get_absolute_media_url($path)
  391. {
  392. // XXX: This will fail if you're symlinking the lifestream directory in
  393. $path = str_replace(trailingslashit(WP_CONTENT_DIR), '', $path);
  394. return str_replace('\\', '/', trailingslashit(WP_CONTENT_URL).$path);
  395. }
  396. function get_theme_filepath($filename)
  397. {
  398. $path = $this->get_filepath_for_theme($filename, $this->get_option('theme', 'default'));
  399. if (!is_file($path))
  400. {
  401. $path = $this->get_filepath_for_theme($filename, 'default');
  402. }
  403. return $path;
  404. }
  405. function get_filepath_for_theme($filename, $theme='default')
  406. {
  407. if (!array_key_exists($theme, $this->themes))
  408. {
  409. throw new Exception('Theme is not valid.');
  410. }
  411. return lifestream_path_join($this->themes[$theme]['__path'], $filename);
  412. }
  413. function validate_image($url)
  414. {
  415. // // Check the extension
  416. // $bits = explode('.', basename($url));
  417. // if (count($bits) > 1)
  418. // {
  419. // $ext = $bits[count($bits)-1];
  420. // return (in_array($ext, $this->valid_image_extensions));
  421. // }
  422. $handler = $this->get_option('url_handler');
  423. $use_fsock = true;
  424. if (($handler == 'auto' && function_exists('curl_init')) || $handler == 'curl')
  425. {
  426. $use_fsock = false;
  427. }
  428. $file = new SimplePie_File($url, 10, 5, null, SIMPLEPIE_USERAGENT, $use_fsock);
  429. if (!$file->success)
  430. {
  431. return false;
  432. }
  433. // Attempt to check content type
  434. if (!empty($file->headers['content-type']))
  435. {
  436. return (in_array($file->headers['content-type'], $this->valid_image_types));
  437. }
  438. // Use GD if we can
  439. if (function_exists('imagecreatefromstring'))
  440. {
  441. return (imagecreatefromstring($file->body) !== false);
  442. }
  443. // Everything has failed, we'll just let it pass
  444. return true;
  445. }
  446. // options and their default values
  447. protected $_options = array(
  448. 'day_format' => 'F jS',
  449. 'hour_format' => 'g:ia',
  450. 'number_of_items' => '50',
  451. 'date_interval' => '1 month',
  452. 'digest_title' => 'Daily Digest for %s',
  453. 'digest_body' => '%1$s',
  454. 'digest_category' => '1',
  455. 'digest_author' => '1',
  456. 'daily_digest' => '0',
  457. 'digest_interval' => 'daily',
  458. 'digest_time' => '0',
  459. 'update_interval' => '15',
  460. 'show_owners' => '0',
  461. 'use_ibox' => '1',
  462. 'show_credits' => '1',
  463. 'hide_details_default' => '1',
  464. 'url_handler' => 'auto',
  465. 'feed_items' => '10',
  466. 'truncate_length' => '128',
  467. 'theme' => 'default',
  468. 'icons' => 'default',
  469. 'extension_dir' => '',
  470. 'theme_dir' => '',
  471. 'icon_dir' => '',
  472. 'links_new_windows' => '0',
  473. 'truncate_interval' => '0',
  474. );
  475. function __construct()
  476. {
  477. $this->path = WP_CONTENT_URL . '/plugins/lifestream';
  478. $this->_optioncache = null;
  479. add_action('admin_menu', array(&$this, 'options_menu'));
  480. add_action('wp_head', array(&$this, 'header'));
  481. add_filter('the_content', array(&$this, 'embed_callback'));
  482. add_action('init', array(&$this, 'init'));
  483. add_filter('cron_schedules', array(&$this, 'get_cron_schedules'));
  484. add_action('lifestream_digest_cron', array(&$this, 'digest_update'));
  485. add_action('lifestream_cron', array(&$this, 'update'));
  486. add_action('lifestream_cleanup', array(&$this, 'cleanup_history'));
  487. add_action('template_redirect', array($this, 'template_redirect'));
  488. register_post_type('lsevent', array('public' => false));
  489. register_activation_hook(LIFESTREAM_PLUGIN_FILE, array(&$this, 'activate'));
  490. register_deactivation_hook(LIFESTREAM_PLUGIN_FILE, array(&$this, 'deactivate'));
  491. }
  492. function truncate($string, $length=128)
  493. {
  494. if (!($length > 0)) return $string;
  495. if (strlen($string) > $length)
  496. {
  497. $string = substr($string, 0, $length-3).'...';
  498. }
  499. return $string;
  500. }
  501. // To be quite honest, WordPress should be doing this kind of magic itself.
  502. function _populate_option_cache()
  503. {
  504. if (!$this->_optioncache)
  505. {
  506. $this->_optioncache = (array)get_option('lifestream_options');
  507. if (!$this->_optioncache) $this->_optioncache = (array)$this->_options;
  508. }
  509. }
  510. /**
  511. * Fetches the value of an option. Returns `null` if the option is not set.
  512. */
  513. function get_option($option, $default=null)
  514. {
  515. $this->_populate_option_cache();
  516. if (!isset($this->_optioncache[$option])) $value = $default;
  517. else
  518. {
  519. $value = $this->_optioncache[$option];
  520. }
  521. if (empty($value)) $value = $default;
  522. return $value;
  523. }
  524. /**
  525. * Removes an option.
  526. */
  527. function delete_option($option)
  528. {
  529. $this->_populate_option_cache();
  530. unset($this->_optioncache[$option]);
  531. update_option('lifestream_options', $this->_optioncache);
  532. }
  533. /**
  534. * Updates the value of an option.
  535. */
  536. function update_option($option, $value)
  537. {
  538. $this->_populate_option_cache();
  539. $this->_optioncache[$option] = $value;
  540. update_option('lifestream_options', $this->_optioncache);
  541. }
  542. /**
  543. * Sets an option if it doesn't exist.
  544. */
  545. function add_option($option, $value)
  546. {
  547. $this->_populate_option_cache();
  548. if (!array_key_exists($option, $this->_optioncache) || $this->_optioncache[$option] === '')
  549. {
  550. $this->_optioncache[$option] = $value;
  551. update_option('lifestream_options', $this->_optioncache);
  552. }
  553. }
  554. function __($text, $params=null)
  555. {
  556. if (!is_array($params))
  557. {
  558. $params = func_get_args();
  559. $params = array_slice($params, 1);
  560. }
  561. return vsprintf(__($text, 'lifestream'), $params);
  562. }
  563. function _e($text, $params=null)
  564. {
  565. if (!is_array($params))
  566. {
  567. $params = func_get_args();
  568. $params = array_slice($params, 1);
  569. }
  570. echo vsprintf(__($text, 'lifestream'), $params);
  571. }
  572. function init()
  573. {
  574. global $wpdb;
  575. $offset = get_option('gmt_offset') * 3600;
  576. define('LIFESTREAM_DATE_OFFSET', $offset);
  577. load_plugin_textdomain('lifestream', false, 'lifestream/locales');
  578. $page = (isset($_GET['page']) ? $_GET['page'] : null);
  579. if (is_admin() && lifestream_str_startswith($page, 'lifestream'))
  580. {
  581. wp_enqueue_script('jquery');
  582. wp_enqueue_script('admin-forms');
  583. }
  584. add_feed('lifestream-feed', 'lifestream_rss_feed');
  585. $this->is_buddypress = (function_exists('bp_is_blog_page') ? true : false);
  586. // If this is an update we need to force reactivation
  587. if (LIFESTREAM_VERSION != $this->get_option('_version'))
  588. {
  589. $this->get_option('_version');
  590. $this->deactivate();
  591. $this->activate();
  592. }
  593. }
  594. function is_lifestream_event()
  595. {
  596. return (is_single() && get_post_type() == 'lsevent');
  597. }
  598. function is_lifestream_home()
  599. {
  600. global $wp_query;
  601. return (@$_GET['cp'] == 'lifestream');
  602. }
  603. function template_redirect()
  604. {
  605. global $ls_template;
  606. $lifestream = $this;
  607. if ($this->is_lifestream_event())
  608. {
  609. include($this->get_template('event.php'));
  610. exit;
  611. }
  612. else if ($this->is_lifestream_home())
  613. {
  614. $ls_template->setup_events();
  615. include($this->get_template('home.php'));
  616. exit;
  617. }
  618. }
  619. function get_template($template)
  620. {
  621. if (file_exists(TEMPLATEPATH.'/lifestream/'.$template))
  622. {
  623. return TEMPLATEPATH.'lifestream/'.$template;
  624. return;
  625. }
  626. return LIFESTREAM_PATH . '/templates/'.$template;
  627. }
  628. function log_error($message, $feed_id=null)
  629. {
  630. global $wpdb;
  631. if ($feed_id)
  632. {
  633. $result = $wpdb->query($wpdb->prepare("INSERT INTO `".$wpdb->prefix."lifestream_error_log` (`feed_id`, `message`, `timestamp`) VALUES (%s, %s, %d)", $wpdb->escape($feed_id), $wpdb->escape($message), time()));
  634. }
  635. else
  636. {
  637. $result = $wpdb->query($wpdb->prepare("INSERT INTO `".$wpdb->prefix."lifestream_error_log` (`feed_id`, `message`, `timestamp`) VALUES (NULL, %s, %d)", $wpdb->escape($message), time()));
  638. }
  639. }
  640. function get_anchor_html($label, $href, $attrs=array())
  641. {
  642. // TODO: this might need to be optimized as string management is typically slow
  643. if ($this->get_option('links_new_windows') && empty($attrs['target']))
  644. {
  645. $attrs['target'] = '_blank';
  646. }
  647. $attrs['href'] = $href;
  648. $html = '<a';
  649. foreach ($attrs as $key=>$value)
  650. {
  651. $html .= ' '.$key.'="'.$value.'"';
  652. }
  653. $html .= '>'.$label.'</a>';
  654. return $html;
  655. }
  656. function get_digest_interval()
  657. {
  658. $interval = $this->get_option('digest_interval');
  659. switch ($interval)
  660. {
  661. case 'weekly':
  662. return 3600*24*7;
  663. case 'daily':
  664. return 3600*24;
  665. case 'hourly':
  666. return 3600;
  667. }
  668. }
  669. function get_cron_schedules($cron)
  670. {
  671. $interval = (int)$this->get_option('update_interval', 15);
  672. if (!($interval > 0)) $interval = 15;
  673. $cron['lifestream'] = array(
  674. 'interval' => $interval * 60,
  675. 'display' => $this->__('On Lifestream update')
  676. );
  677. $cron['lifestream_digest'] = array(
  678. 'interval' => (int)$this->get_digest_interval(),
  679. 'display' => $this->__('On Lifestream daily digest update')
  680. );
  681. return $cron;
  682. }
  683. function get_single_event($feed_type)
  684. {
  685. $events = $this->get_events(array('feed_types'=>array($feed_type), 'limit'=>1, 'break_groups'=>true));
  686. $event = $events[0];
  687. return $event;
  688. }
  689. function generate_unique_id()
  690. {
  691. return uniqid('ls_', true);
  692. }
  693. function digest_update()
  694. {
  695. global $wpdb;
  696. if ($this->get_option('daily_digest') != '1') return;
  697. $interval = $this->get_digest_interval();
  698. $options = array(
  699. 'id' => $this->generate_unique_id(),
  700. );
  701. $now = time();
  702. // If there was a previous digest, we show only events since it
  703. $from = $this->get_option('_last_digest');
  704. // Otherwise we show events within the interval period
  705. if (!$from) $from = $now - $interval;
  706. // make sure the post doesn't exist
  707. $results = $wpdb->get_results($wpdb->prepare("SELECT `post_id` FROM `".$wpdb->prefix."postmeta` WHERE `meta_key` = '_lifestream_digest_date' AND `meta_value` = %d LIMIT 0, 1", $now));
  708. if ($results) continue;
  709. $sql = $wpdb->prepare("SELECT t1.*, t2.`options` FROM `".$wpdb->prefix."lifestream_event_group` as `t1` INNER JOIN `".$wpdb->prefix."lifestream_feeds` as t2 ON t1.`feed_id` = t2.`id` WHERE t1.`timestamp` > %s AND t1.`timestamp` < %s ORDER BY t1.`timestamp` ASC", $from, $now);
  710. $results =& $wpdb->get_results($sql);
  711. $events = array();
  712. foreach ($results as &$result)
  713. {
  714. $events[] = new Lifestream_EventGroup($this, $result);
  715. }
  716. if (count($events))
  717. {
  718. ob_start();
  719. if (!include($this->get_theme_filepath('digest.inc.php'))) return;
  720. $content = sprintf($this->get_option('digest_body'), ob_get_clean(), date($this->get_option('day_format'), $now), count($events));
  721. $data = array(
  722. 'post_content' => $wpdb->escape($content),
  723. 'post_title' => $wpdb->escape(sprintf($this->get_option('digest_title'), date($this->get_option('day_format'), $now), date($this->get_option('hour_format'), $now))),
  724. 'post_date' => date('Y-m-d H:i:s', $now),
  725. 'post_category' => array($this->get_option('digest_category')),
  726. 'post_status' => 'publish',
  727. 'post_author' => $wpdb->escape($this->get_option('digest_author')),
  728. );
  729. $post_id = wp_insert_post($data);
  730. add_post_meta($post_id, '_lifestream_digest_date', $now, true);
  731. }
  732. $this->update_option('_last_digest', $now);
  733. }
  734. // page output
  735. function options_menu()
  736. {
  737. global $wpdb;
  738. wp_enqueue_script('postbox');
  739. if (function_exists('add_menu_page'))
  740. {
  741. $basename = basename(LIFESTREAM_PLUGIN_FILE);
  742. $results =& $wpdb->get_results("SELECT COUNT(*) as `count` FROM `".$wpdb->prefix."lifestream_error_log` WHERE has_viewed = 0");
  743. $errors = $results[0]->count;
  744. add_menu_page('Lifestream', 'Lifestream', 'edit_posts', $basename, array(&$this, 'options_page'));
  745. add_submenu_page($basename, $this->__('Lifestream Feeds'), $this->__('Feeds'), 'level_1', $basename, array(&$this, 'options_page'));
  746. add_submenu_page($basename, $this->__('Lifestream Events'), $this->__('Events'), 'edit_posts', 'lifestream-events.php', array(&$this, 'options_page'));
  747. add_submenu_page($basename, $this->__('Lifestream Settings'), $this->__('Settings'), 'manage_options', 'lifestream-settings.php', array(&$this, 'options_page'));
  748. add_submenu_page($basename, $this->__('Lifestream Change Log'), $this->__('Change Log'), 'edit_posts', 'lifestream-changelog.php', array(&$this, 'options_page'));
  749. add_submenu_page($basename, $this->__('Lifestream Errors'), $this->__('Errors (%d)', $errors), 'edit_posts', 'lifestream-errors.php', array(&$this, 'options_page'));
  750. add_submenu_page($basename, $this->__('Lifestream Maintenance'), $this->__('Maintenance / Debug', $errors), 'manage_options', 'lifestream-maintenance.php', array(&$this, 'options_page'));
  751. add_submenu_page($basename, $this->__('Lifestream Support Forums'), $this->__('Support Forums'), 'edit_posts', 'lifestream-forums.php', array(&$this, 'options_page'));
  752. }
  753. }
  754. function header()
  755. {
  756. echo '<script type="text/javascript" src="'.$this->path.'/lifestream.js"></script>';
  757. echo '<link rel="stylesheet" type="text/css" media="screen" href="'.$this->get_theme_media_url('lifestream.css').'"/>';
  758. }
  759. function options_page()
  760. {
  761. global $wpdb, $userdata;
  762. $wpdb->show_errors();
  763. $this->install();
  764. get_currentuserinfo();
  765. $date_format = sprintf('%s @ %s', $this->get_option('day_format'), $this->get_option('hour_format'));
  766. $basename = basename(LIFESTREAM_PLUGIN_FILE);
  767. $errors = array();
  768. $message = null;
  769. switch ($_GET['page'])
  770. {
  771. case 'lifestream-maintenance.php':
  772. if ($_POST['resetcron'])
  773. {
  774. $this->reschedule_cron();
  775. $message = $this->__('Cron timers have been reset.');
  776. }
  777. elseif ($_POST['restore'])
  778. {
  779. $this->restore_options();
  780. $message = $this->__('Default options have been restored.');
  781. }
  782. elseif ($_POST['restoredb'])
  783. {
  784. $this->restore_database();
  785. $message = $this->__('Default database has been restored.');
  786. }
  787. break;
  788. case 'lifestream-events.php':
  789. switch ((isset($_REQUEST['op']) ? strtolower($_REQUEST['op']) : null))
  790. {
  791. case 'delete':
  792. if (!($ids = $_REQUEST['id'])) break;
  793. if (!is_array($ids)) $ids = array($ids);
  794. foreach ($ids as $id)
  795. {
  796. $result =& $wpdb->get_results($wpdb->prepare("SELECT `id`, `feed_id`, `timestamp`, `owner_id` FROM `".$wpdb->prefix."lifestream_event` WHERE `id` = %d", $id));
  797. if (!$result)
  798. {
  799. $errors[] = $this->__('The selected feed was not found.');
  800. }
  801. elseif (!current_user_can('manage_options') && $result[0]->owner_id != $userdata->ID)
  802. {
  803. $errors[] = $this->__('You do not have permission to do that.');
  804. }
  805. else
  806. {
  807. $result =& $result[0];
  808. $wpdb->query($wpdb->prepare("UPDATE `".$wpdb->prefix."lifestream_event` SET `visible` = 0 WHERE `id` = %d", $result->id));
  809. $wpdb->query($wpdb->prepare("UPDATE `".$wpdb->prefix."lifestream_event_group` SET `visible` = 0 WHERE `event_id` = %d", $result->id));
  810. // Now we have to update the batch if it exists.
  811. $group =& $wpdb->get_results($wpdb->prepare("SELECT `id` FROM `".$wpdb->prefix."lifestream_event_group` WHERE `event_id` IS NULL AND DATE(FROM_UNIXTIME(`timestamp`)) = DATE(FROM_UNIXTIME(%d)) AND `feed_id` = %d LIMIT 0, 1", $result->timestamp, $result->feed_id));
  812. if (count($group) == 1)
  813. {
  814. $group =& $group[0];
  815. $results =& $wpdb->get_results($wpdb->prepare("SELECT `data`, `link` FROM `".$wpdb->prefix."lifestream_event` WHERE `feed_id` = %d AND `visible` = 1 AND DATE(FROM_UNIXTIME(`timestamp`)) = DATE(FROM_UNIXTIME(%d))", $result->feed_id, $result->timestamp));
  816. if (count($results))
  817. {
  818. $events = array();
  819. foreach ($results as &$result)
  820. {
  821. $result->data = unserialize($result->data);
  822. $result->data['link'] = $result->link;
  823. $events[] = $result->data;
  824. }
  825. $wpdb->query($wpdb->prepare("UPDATE `".$wpdb->prefix."lifestream_event_group` SET `data` = %s, `total` = %d, `updated` = 1 WHERE `id` = %d", $wpdb->escape(serialize($events)), count($events), $group->id));
  826. }
  827. else
  828. {
  829. $wpdb->query($wpdb->prepare("DELETE FROM `".$wpdb->prefix."lifestream_event_group` WHERE `id` = %d", $group->id));
  830. }
  831. }
  832. else
  833. {
  834. $wpdb->query($wpdb->prepare("DELETE FROM `".$wpdb->prefix."lifestream_event_group` WHERE `event_id` = %d", $result->id));
  835. }
  836. }
  837. $message = $this->__('The selected events were hidden.');
  838. }
  839. break;
  840. }
  841. break;
  842. case 'lifestream-settings.php':
  843. if (!empty($_POST['save']))
  844. {
  845. foreach (array_keys($this->_options) as $value)
  846. {
  847. $this->update_option($value, (isset($_POST['lifestream_'.$value]) ? stripslashes($_POST['lifestream_'.$value]) : '0'));
  848. }
  849. // We need to make sure the cron runs now
  850. $this->reschedule_cron();
  851. }
  852. break;
  853. default:
  854. $feedmsgs = array();
  855. switch ((isset($_REQUEST['op']) ? strtolower($_REQUEST['op']) : null))
  856. {
  857. case 'refreshall':
  858. $results = $this->update_all($userdata->ID);
  859. foreach ($results as $id=>$result)
  860. {
  861. if (is_int($result)) $feedmsgs[$id] = $result;
  862. else $errors[] = $this->__('There was an error refreshing the selected feed: ID %s', $id);
  863. }
  864. $message = $this->__('All of your feeds have been refreshed.');
  865. break;
  866. case 'refresh':
  867. if (!$_REQUEST['id']) break;
  868. foreach ($_REQUEST['id'] as $id)
  869. {
  870. $result =& $wpdb->get_results($wpdb->prepare("SELECT * FROM `".$wpdb->prefix."lifestream_feeds` WHERE `id` = %d LIMIT 0, 1", $id));
  871. if (!$result)
  872. {
  873. $errors[] = $this->__('The selected feed was not found.');
  874. }
  875. elseif (!current_user_can('manage_options') && $result[0]->owner_id != $userdata->ID)
  876. {
  877. $errors[] = $this->__('You do not have permission to do that.');
  878. }
  879. else
  880. {
  881. $instance = Lifestream_Feed::construct_from_query_result($this, $result[0]);
  882. $msg_arr = $instance->refresh();
  883. if ($msg_arr[0] !== false)
  884. {
  885. $message = $this->__('The selected feeds and their events have been refreshed.');
  886. $feedmsgs[$instance->id] = $msg_arr[1];
  887. }
  888. else
  889. {
  890. $errors[] = $this->__('There was an error refreshing the selected feed: ID %s', $instance->id);
  891. }
  892. }
  893. }
  894. break;
  895. case 'pause':
  896. if (!$_REQUEST['id']) break;
  897. $ids = array();
  898. foreach ($_REQUEST['id'] as $id)
  899. {
  900. $ids[] = (int)$id;
  901. }
  902. if (!empty($ids))
  903. {
  904. if (current_user_can('manage_options'))
  905. {
  906. $wpdb->query($wpdb->prepare("UPDATE `".$wpdb->prefix."lifestream_feeds` SET `active` = 0 WHERE `id` IN ('%s')", implode("','", $ids)));
  907. }
  908. else
  909. {
  910. $wpdb->query($wpdb->prepare("UPDATE `".$wpdb->prefix."lifestream_feeds` SET `active` = 1 WHERE `id` IN ('%s') AND `owner_id` = %s", implode("','", $ids), $userdata->ID));
  911. }
  912. $message = $this->__('The selected feeds have been paused, and events will not be refreshed.');
  913. }
  914. break;
  915. case 'unpause':
  916. if (!$_REQUEST['id']) break;
  917. $ids = array();
  918. foreach ($_REQUEST['id'] as $id)
  919. {
  920. $ids[] = (int)$id;
  921. }
  922. if (!empty($ids))
  923. {
  924. if (current_user_can('manage_options'))
  925. {
  926. $wpdb->query($wpdb->prepare("UPDATE `".$wpdb->prefix."lifestream_feeds` SET `active` = 1 WHERE `id` IN ('%s')", implode("','", $ids)));
  927. }
  928. else
  929. {
  930. $wpdb->query($wpdb->prepare("UPDATE `".$wpdb->prefix."lifestream_feeds` SET `active` = 0 WHERE `id` IN ('%s') AND `owner_id` = %s", implode("','", $ids), $userdata->ID));
  931. }
  932. $message = $this->__('The selected feeds have been unpaused, and events will now be refreshed.');
  933. }
  934. break;
  935. case 'delete':
  936. if (!$_REQUEST['id']) break;
  937. foreach ($_REQUEST['id'] as $id)
  938. {
  939. $result =& $wpdb->get_results($wpdb->prepare("SELECT * FROM `".$wpdb->prefix."lifestream_feeds` WHERE `id` = %d LIMIT 0, 1", $id));
  940. if (!$result)
  941. {
  942. $errors[] = $this->__('The selected feed was not found.');
  943. }
  944. elseif (!current_user_can('manage_options') && $result[0]->owner_id != $userdata->ID)
  945. {
  946. $errors[] = $this->__('You do not have permission to do that.');
  947. }
  948. else
  949. {
  950. $instance = Lifestream_Feed::construct_from_query_result($this, $result[0]);
  951. $instance->delete();
  952. $message = $this->__('The selected feeds and all related events has been removed.');
  953. }
  954. }
  955. break;
  956. case 'edit':
  957. $result =& $wpdb->get_results($wpdb->prepare("SELECT * FROM `".$wpdb->prefix."lifestream_feeds` WHERE `id` = %d LIMIT 0, 1", $_GET['id']));
  958. if (!$result)
  959. {
  960. $errors[] = $this->__('The selected feed was not found.');
  961. }
  962. elseif (!current_user_can('manage_options') && $result[0]->owner_id != $userdata->ID)
  963. {
  964. $errors[] = $this->__('You do not have permission to do that.');
  965. }
  966. else
  967. {
  968. $instance = Lifestream_Feed::construct_from_query_result($this, $result[0]);
  969. $options = $instance->get_options();
  970. if (@$_POST['save'])
  971. {
  972. $values = array();
  973. foreach ($options as $option=>$option_meta)
  974. {
  975. if ($option_meta[1] && !$_POST[$option])
  976. {
  977. $errors[] = $option_meta[0].' is required.';
  978. }
  979. else
  980. {
  981. $values[$option] = stripslashes($_POST[$option]);
  982. }
  983. }
  984. if ($instance->get_constant('MUST_GROUP'))
  985. {
  986. $values['grouped'] = 1;
  987. }
  988. elseif ($instance->get_constant('CAN_GROUP'))
  989. {
  990. $values['grouped'] = $_POST['grouped'];
  991. }
  992. if ($instance->get_constant('HAS_EXCERPTS'))
  993. {
  994. $values['excerpt'] = $_POST['excerpt'];
  995. }
  996. $values['feed_label'] = $_POST['feed_label'];
  997. $values['icon_url'] = $_POST['icon_url'];
  998. $values['auto_icon'] = @$_POST['auto_icon'];
  999. if ($_POST['owner'] != $instance->owner_id && current_user_can('manage_options'))
  1000. {
  1001. $usero = new WP_User($_POST['owner']);
  1002. $owner = $usero->data;
  1003. $instance->owner_id = $_POST['owner'];
  1004. $instance->owner = $owner->display_name;
  1005. }
  1006. if (!count($errors))
  1007. {
  1008. $instance->options = $values;
  1009. $instance->save();
  1010. unset($_POST);
  1011. }
  1012. }
  1013. elseif (@$_POST['truncate'])
  1014. {
  1015. $instance->truncate();
  1016. $instance->refresh();
  1017. }
  1018. }
  1019. break;
  1020. case 'add':
  1021. if ($_POST)
  1022. {
  1023. $class_name = $this->get_feed($_GET['feed']);
  1024. if (!$class_name) break;
  1025. $feed = new $class_name($this);
  1026. $values = array();
  1027. $options = $feed->get_options();
  1028. foreach ($options as $option=>$option_meta)
  1029. {
  1030. if ($option_meta[1] && !$_POST[$option])
  1031. {
  1032. $errors[] = $option_meta[0].' is required.';
  1033. }
  1034. else
  1035. {
  1036. $values[$option] = stripslashes($_POST[$option]);
  1037. }
  1038. }
  1039. if ($feed->get_constant('MUST_GROUP'))
  1040. {
  1041. $values['grouped'] = 1;
  1042. }
  1043. elseif ($feed->get_constant('CAN_GROUP'))
  1044. {
  1045. $values['grouped'] = @$_POST['grouped'];
  1046. }
  1047. if ($feed->get_constant('HAS_EXCERPTS'))
  1048. {
  1049. $values['excerpt'] = $_POST['excerpt'];
  1050. }
  1051. $values['feed_label'] = $_POST['feed_label'];
  1052. $values['icon_url'] = $_POST['icon_url'];
  1053. $values['auto_icon'] = @$_POST['auto_icon'];
  1054. if (current_user_can('manage_options'))
  1055. {
  1056. $feed->owner_id = $_POST['owner'];
  1057. $usero = new WP_User($feed->owner_id);
  1058. $owner = $usero->data;
  1059. $feed->owner = $owner->display_name;
  1060. }
  1061. else
  1062. {
  1063. $feed->owner_id = $userdata->ID;
  1064. $feed->owner = $userdata->display_name;
  1065. }
  1066. $feed->options = $values;
  1067. if (!count($errors))
  1068. {
  1069. if (!($error = $feed->test()))
  1070. {
  1071. $result = $feed->save();
  1072. if ($result !== false)
  1073. {
  1074. unset($_POST);
  1075. unset($_REQUEST['op']);
  1076. $msg_arr = $feed->refresh(null, true);
  1077. if ($msg_arr[0] !== false)
  1078. {
  1079. $message = $this->__('A new %s feed was added to your Lifestream.', $feed->get_constant('NAME'));
  1080. $feedmsgs[$feed->id] = $msg_arr[1];
  1081. }
  1082. }
  1083. }
  1084. else
  1085. {
  1086. $errors[] = $error;
  1087. }
  1088. }
  1089. }
  1090. break;
  1091. }
  1092. break;
  1093. }
  1094. $lifestream = &$this;
  1095. ob_start();
  1096. ?>
  1097. <style type="text/css">
  1098. .feedlist { margin: 0; padding: 0; }
  1099. .feedlist li { list-style: none; display: inline; }
  1100. .feedlist li a { float: left; display: block; padding: 2px; margin: 1px; width: 23%; text-decoration: none; }
  1101. .feedlist li a:hover { background-color: #e9e9e9; }
  1102. .success { color: #397D33; background-color: #D1FBCA; }
  1103. .error { border-color: #E25F53; color: #E25F53; }
  1104. td.icon { padding: 7px 0 9px 10px; }
  1105. </style>
  1106. <br />
  1107. <?php
  1108. if (count($errors)) { ?>
  1109. <div id="message" class="error"><p><strong><?php $this->_e('There were errors with your request:') ?></strong></p><ul>
  1110. <?php foreach ($errors as $error) { ?>
  1111. <li><?php echo nl2br(Lifestream_Feed::parse_urls(htmlspecialchars($error))); ?></li>
  1112. <?php } ?>
  1113. </ul></div>
  1114. <?php } elseif ($message) { ?>
  1115. <div id="message" class="updated fade"><p><strong><?php echo $message; ?></strong></p></div>
  1116. <?php } ?>
  1117. <div class="wrap">
  1118. <?php
  1119. switch ($_GET['page'])
  1120. {
  1121. case 'lifestream-errors.php':
  1122. $page = (!empty($_GET['paged']) ? $_GET['paged'] : 1);
  1123. switch ((isset($_REQUEST['op']) ? strtolower($_REQUEST['op']) : null))
  1124. {
  1125. case 'clear':
  1126. $wpdb->query("DELETE FROM `".$wpdb->prefix."lifestream_error_log`");
  1127. break;
  1128. }
  1129. $start = ($page-1)*LIFESTREAM_ERRORS_PER_PAGE;
  1130. $end = $page*LIFESTREAM_ERRORS_PER_PAGE;
  1131. $wpdb->query("UPDATE `".$wpdb->prefix."lifestream_error_log` SET has_viewed = 1");
  1132. $results =& $wpdb->get_results("SELECT COUNT(*) as `count` FROM `".$wpdb->prefix."lifestream_error_log`");
  1133. $number_of_pages = ceil($results[0]->count/LIFESTREAM_EVENTS_PER_PAGE);
  1134. $results =& $wpdb->get_results($wpdb->prepare("SELECT t1.*, t2.`feed`, t2.`options` FROM `".$wpdb->prefix."lifestream_error_log` as t1 LEFT JOIN `".$wpdb->prefix."lifestream_feeds` as t2 ON t1.`feed_id` = t2.`id` ORDER BY t1.`timestamp` DESC LIMIT %d, %d", $start, $end));
  1135. include(LIFESTREAM_PATH . '/pages/errors.inc.php');
  1136. break;
  1137. case 'lifestream-maintenance.php':
  1138. include(LIFESTREAM_PATH . '/pages/maintenance.inc.php');
  1139. break;
  1140. case 'lifestream-changelog.php':
  1141. include(LIFESTREAM_PATH . '/pages/changelog.inc.php');
  1142. break;
  1143. case 'lifestream-forums.php':
  1144. include(LIFESTREAM_PATH . '/pages/forums.inc.php');
  1145. break;
  1146. case 'lifestream-settings.php':
  1147. $lifestream_digest_intervals = array(
  1148. 'weekly' => $this->__('Weekly'),
  1149. 'daily' => $this->__('Daily'),
  1150. 'hourly' => $this->__('Hourly'),
  1151. );
  1152. include(LIFESTREAM_PATH . '/pages/settings.inc.php');
  1153. break;
  1154. case 'lifestream-events.php':
  1155. $page = (!empty($_GET['paged']) ? $_GET['paged'] : 1);
  1156. $start = ($page-1)*LIFESTREAM_EVENTS_PER_PAGE;
  1157. $end = $page*LIFESTREAM_EVENTS_PER_PAGE;
  1158. if (!current_user_can('manage_options'))
  1159. {
  1160. $rows =& $wpdb->get_row($wpdb->prepare("SELECT COUNT(*) as `count` FROM `".$wpdb->prefix."lifestream_event` WHERE `owner_id` = %d", $userdata->ID));
  1161. $number_of_pages = ceil($rows->count/LIFESTREAM_EVENTS_PER_PAGE);
  1162. $rows =& $wpdb->get_results($wpdb->prepare("SELECT t1.*, t2.`feed`, t2.`options` FROM `".$wpdb->prefix."lifestream_event` as t1 JOIN `".$wpdb->prefix."lifestream_feeds` as t2 ON t1.`feed_id` = t2.`id` WHERE t1.`owner_id` = %d ORDER BY t1.`timestamp` DESC LIMIT %d, %d", $userdata->ID, $start, $end));
  1163. }
  1164. else
  1165. {
  1166. $rows =& $wpdb->get_row("SELECT COUNT(*) as `count` FROM `".$wpdb->prefix."lifestream_event`");
  1167. $number_of_pages = ceil($rows->count/LIFESTREAM_EVENTS_PER_PAGE);
  1168. $rows =& $wpdb->get_results($wpdb->prepare("SELECT t1.*, t2.`feed`, t2.`options` FROM `".$wpdb->prefix."lifestream_event` as t1 JOIN `".$wpdb->prefix."lifestream_feeds` as t2 ON t1.`feed_id` = t2.`id` ORDER BY t1.`timestamp` DESC LIMIT %d, %d", $start, $end));
  1169. }
  1170. $results = array();
  1171. foreach ($rows as $result)
  1172. {
  1173. $results[] = new Lifestream_Event($lifestream, $result);
  1174. }
  1175. unset($rows);
  1176. include(LIFESTREAM_PATH . '/pages/events.inc.php');
  1177. break;
  1178. default:
  1179. switch ((isset($_REQUEST['op']) ? strtolower($_REQUEST['op']) : null))
  1180. {
  1181. case 'edit':
  1182. include(LIFESTREAM_PATH . '/pages/edit-feed.inc.php');
  1183. break;
  1184. case 'add':
  1185. $identifier = $_GET['feed'];
  1186. $class_name = $this->get_feed($identifier);
  1187. if (!$class_name) break;
  1188. $feed = new $class_name($this);
  1189. $options = $feed->get_options();
  1190. include(LIFESTREAM_PATH . '/pages/add-feed.inc.php');
  1191. break;
  1192. default:
  1193. $page = (!empty($_GET['paged']) ? $_GET['paged'] : 1);
  1194. $start = ($page-1)*LIFESTREAM_FEEDS_PER_PAGE;
  1195. $end = $page*LIFESTREAM_FEEDS_PER_PAGE;
  1196. if (!current_user_can('manage_options'))
  1197. {
  1198. $rows =& $wpdb->get_row($wpdb->prepare("SELECT COUNT(*) as `count` FROM `".$wpdb->prefix."lifestream_feeds` WHERE `owner_id` = %d", $userdata->ID));
  1199. $number_of_pages = ceil($rows->count/LIFESTREAM_FEEDS_PER_PAGE);
  1200. $rows =& $wpdb->get_results($wpdb->prepare("SELECT t1.*, (SELECT COUNT(1) FROM `".$wpdb->prefix."lifestream_event` WHERE `feed_id` = t1.`id`) as `events` FROM `".$wpdb->prefix."lifestream_feeds` as t1 WHERE t1.`owner_id` = %d ORDER BY `id` LIMIT %d, %d", $userdata->ID, $start, $end));
  1201. }
  1202. else
  1203. {
  1204. $rows =& $wpdb->get_row("SELECT COUNT(*) as `count` FROM `".$wpdb->prefix."lifestream_feeds`");
  1205. $number_of_pages = ceil($rows->count/LIFESTREAM_FEEDS_PER_PAGE);
  1206. $rows =& $wpdb->get_results($wpdb->prepare("SELECT t1.*, (SELECT COUNT(1) FROM `".$wpdb->prefix."lifestream_event` WHERE `feed_id` = t1.`id`) as `events` FROM `".$wpdb->prefix."lifestream_feeds` as t1 ORDER BY `id` LIMIT %d, %d", $start, $end));
  1207. }
  1208. $results = array();
  1209. foreach ($rows as $result)
  1210. {
  1211. $results[] = Lifestream_Feed::construct_from_query_result($this, $result);
  1212. }
  1213. if ($results !== false)
  1214. {
  1215. include(LIFESTREAM_PATH . '/pages/feeds.inc.php');
  1216. }
  1217. break;
  1218. }
  1219. break;
  1220. }
  1221. ?>
  1222. </div>
  1223. <?php
  1224. ob_end_flush();
  1225. }
  1226. /**
  1227. * Cleans up old entries based on the `truncate_interval` setting.
  1228. */
  1229. function cleanup_history()
  1230. {
  1231. $int = $this->get_option('truncate_interval');
  1232. if (!(int)$int) return;
  1233. // the value is in days
  1234. $ts = time()-(int)$int*3600*24;
  1235. $result = $wpdb->query($wpdb->prepare("DELETE FROM `".$wpdb->prefix."lifestream_event` WHERE `timestamp` < %s", $wpdb->escape($ts)));
  1236. $result = $wpdb->query($wpdb->prepare("DELETE FROM `".$wpdb->prefix."lifestream_event_group` WHERE `timestamp` < %s", $wpdb->escape($ts)));
  1237. $result = $wpdb->query($wpdb->prepare("DELETE FROM `".$wpdb->prefix."lifestream_error_log` WHERE `timestamp` < %s", $wpdb->escape($ts)));
  1238. }
  1239. /**
  1240. * Attempts to update all feeds
  1241. */
  1242. function update($user_id=null)
  1243. {
  1244. $event_arr = $this->update_all($user_id);
  1245. $events = 0;
  1246. foreach ($event_arr as $instance=>$result)
  1247. {
  1248. if (is_int($result)) $events += $result;
  1249. }
  1250. return $events;
  1251. }
  1252. function update_all($user_id=null)
  1253. {
  1254. // $user_id is not implemented yet
  1255. global $wpdb;
  1256. $this->update_option('_last_update', time());
  1257. $events = array();
  1258. $results =& $wpdb->get_results("SELECT * FROM `".$wpdb->prefix."lifestream_feeds` WHERE `active` = 1");
  1259. foreach ($results as $result)
  1260. {
  1261. $instance = Lifestream_Feed::construct_from_query_result($this, $result);
  1262. try
  1263. {
  1264. $feed_msg = $instance->refresh();
  1265. $events[$instance->id] = $feed_msg[1];
  1266. }
  1267. catch (Lifestream_FeedFetchError $ex)
  1268. {
  1269. $this->log_error($ex, $instance->id);
  1270. $events[$instance->id] = $ex;
  1271. }
  1272. }
  1273. return $events;
  1274. }
  1275. /**
  1276. * Registers a feed class with Lifestream.
  1277. * @param $class_name {Class} Should extend Lifestream_Extension.
  1278. */
  1279. function register_feed($class_name)
  1280. {
  1281. $this->feeds[lifestream_get_class_constant($class_name, 'ID')] = $class_name;
  1282. // this may be the ugliest thing ever written in PHP, thank you developers!
  1283. $rcl = new ReflectionClass($class_name);
  1284. $this->paths[$class_name] = dirname($rcl->getFileName());
  1285. unset($rcl);
  1286. }
  1287. function get_feed($class_name)
  1288. {
  1289. return $this->feeds[$class_name];
  1290. }
  1291. /**
  1292. * Similar to file_get_contents but will use curl by default.
  1293. */
  1294. function file_get_contents($url)
  1295. {
  1296. $handler = $this->get_option('url_handler');
  1297. $use_fsock = true;
  1298. if (($handler == 'auto' && function_exists('curl_init')) || $handler == 'curl')
  1299. {
  1300. $use_fsock = false;
  1301. }
  1302. $file = new SimplePie_File($url, 10, 5, null, SIMPLEPIE_USERAGENT, $use_fsock);
  1303. if (!$file->success)
  1304. {
  1305. throw new Lifestream_FeedFetchError('Failed to open url: '.$url .' ('.$file->error.')');
  1306. }
  1307. return $file->body;
  1308. }
  1309. /*
  1310. * This is a wrapper function which initiates the callback for the custom tag embedding.
  1311. */
  1312. function embed_callback($content)
  1313. {
  1314. return preg_replace_callback("|\[lifestream(?:\s+([^\]]+))?\]|i", array(&$this, 'embed_handler'), $content);
  1315. return preg_replace_callback("|<\[]lifestream(?:\s+([^>\]+]))?/?[>\]]|i", array(&$this, 'embed_handler'), $content);
  1316. }
  1317. /*
  1318. * This function handles the real meat by handing off the work to helper functions.
  1319. */
  1320. function embed_handler($matches)
  1321. {
  1322. $args = array();
  1323. if (count($matches) > 1)
  1324. {
  1325. preg_match_all("|(?:([a-z_]+)=[\"']?([a-z0-9_-\s,]+)[\"']?)\s*|i", $matches[1], $options);
  1326. for ($i=0; $i<count($options[1]); $i++)
  1327. {
  1328. if ($options[$i]) $args[$options[1][$i]] = $options[2][$i];
  1329. }
  1330. }
  1331. ob_start();
  1332. if (!empty($args['feed_ids'])) $args['feed_ids'] = explode(',', $args['feed_ids']);
  1333. if (!empty($args['user_ids'])) $args['user_ids'] = explode(',', $args['user_ids']);
  1334. if (!empty($args['feed_types'])) $args['feed_types'] = explode(',', $args['feed_types']);
  1335. lifestream($args);
  1336. return ob_get_clean();
  1337. }
  1338. /**
  1339. * Returns the duration from now until timestamp.
  1340. * @param $timestamp {Integer}
  1341. * @param $granularity {Integer}
  1342. * @param $format {String} Date format.
  1343. * @return {String}
  1344. */
  1345. function timesince($timestamp, $granularity=1, $format='Y-m-d H:i:s')
  1346. {
  1347. $difference = time() - $timestamp;
  1348. if ($difference < 0) return 'just now';
  1349. elseif ($difference < 86400*2)
  1350. {
  1351. return $this->duration($difference, $granularity) . ' ago';
  1352. }
  1353. else
  1354. {
  1355. return date($this->get_option('day_format'), $timestamp);
  1356. }
  1357. }
  1358. /**
  1359. * Returns the duration from a difference.
  1360. * @param $difference {Integer}
  1361. * @param $granularity {Integer}
  1362. * @return {String}
  1363. */
  1364. function duration($difference, $granularity=2)
  1365. {
  1366. { // if difference is over 10 days show normal time form
  1367. $periods = array(
  1368. $this->__('w') => 604800,
  1369. $this->__('d') => 86400,
  1370. $this->__('h') => 3600,
  1371. $this->__('m') => 60,
  1372. $this->__('s') => 1
  1373. );
  1374. $output = '';
  1375. foreach ($periods as $key => $value)
  1376. {
  1377. if ($difference >= $value)
  1378. {
  1379. $time = round($difference / $value);
  1380. $difference %= $value;
  1381. $output .= ($output ? ' ' : '').$time.$key;
  1382. //$output .= (($time > 1 && ($key == 'week' || $key == 'day')) ? $key.'s' : $key);
  1383. $granularity--;
  1384. }
  1385. if ($granularity == 0) break;
  1386. }
  1387. return ($output ? $output : '0 seconds');
  1388. }
  1389. }
  1390. function get_cron_task_description($name)
  1391. {
  1392. switch ($name)
  1393. {
  1394. case 'lifestream_cleanup':
  1395. return 'Cleans up old events and error messages.';
  1396. break;
  1397. case 'lifestream_cron':
  1398. return 'Updates all active feeds.';
  1399. break;
  1400. case 'lifestream_digest_cron':
  1401. return 'Creates a daily digest post if enabled.';
  1402. break;
  1403. }
  1404. }
  1405. function restore_options()
  1406. {
  1407. // default options and their values
  1408. foreach ($this->_options as $key=>$value)
  1409. {
  1410. $this->update_option($key, $value);
  1411. }
  1412. $this->update_option('extension_dir', WP_CONTENT_DIR.'/wp-lifestream/extensions/');
  1413. $this->update_option('theme_dir', WP_CONTENT_DIR.'/wp-lifestream/themes/');
  1414. $this->update_option('icon_dir', WP_CONTENT_DIR.'/wp-lifestream/icons/');
  1415. }
  1416. function restore_database()
  1417. {
  1418. global $wpdb;
  1419. $this->safe_query("DROP TABLE `".$wpdb->prefix."lifestream_event`;");
  1420. $this->safe_query("DROP TABLE `".$wpdb->prefix."lifestream_event_group`;");
  1421. $this->safe_query("DROP TABLE `".$wpdb->prefix."lifestream_feeds`;");
  1422. $this->safe_query("DROP TABLE `".$wpdb->prefix."lifestream_error_log`;");
  1423. $this->install_database();
  1424. }
  1425. function reschedule_cron()
  1426. {
  1427. wp_clear_scheduled_hook('lifestream_cron');
  1428. wp_clear_scheduled_hook('lifestream_cleanup');
  1429. wp_clear_scheduled_hook('lifestream_digest_cron');
  1430. wp_schedule_event(time()+60, 'daily', 'lifestream_cleanup');
  1431. // First lifestream cron should not happen instantly, incase we need to reschedule
  1432. wp_schedule_event(time()+60, 'lifestream', 'lifestream_cron');
  1433. // We have to calculate the time for the first digest
  1434. $digest_time = $this->get_option('digest_time');
  1435. $digest_interval = $this->get_option('digest_interval');
  1436. $time = time();
  1437. if ($digest_interval == 'hourly')
  1438. {
  1439. // Start at the next hour
  1440. $time = strtotime(date('Y-m-d H:00:00', strtotime('+1 hour', $time)));
  1441. }
  1442. else
  1443. {
  1444. // If time has already passed for today, set it for tomorrow
  1445. if (date('H') > $digest_time)
  1446. {
  1447. $time = strtotime('+1 day', $time);
  1448. }
  1449. else
  1450. {
  1451. $time = strtotime(date('Y-m-d '.$digest_time.':00:00', $time));
  1452. }
  1453. }
  1454. wp_schedule_event($time, 'lifestream_digest', 'lifestream_digest_cron');
  1455. }
  1456. function deactivate()
  1457. {
  1458. wp_clear_scheduled_hook('lifestream_cron');
  1459. wp_clear_scheduled_hook('lifestream_cleanup');
  1460. wp_clear_scheduled_hook('lifestream_digest_cron');
  1461. }
  1462. /**
  1463. * Initializes the plug-in upon activation.
  1464. */
  1465. function activate()
  1466. {
  1467. global $wpdb, $userdata;
  1468. get_currentuserinfo();
  1469. // Options/database install
  1470. $this->install();
  1471. // Add a feed for this blog
  1472. $results =& $wpdb->get_results("SELECT COUNT(*) as `count` FROM `".$wpdb->prefix."lifestream_feeds`");
  1473. if (!$results[0]->count)
  1474. {
  1475. $rss_url = get_bloginfo('rss2_url');
  1476. $options = array('url' => $rss_url);
  1477. $feed = new Lifestream_BlogFeed($this, $options);
  1478. $feed->owner = $userdata->display_name;
  1479. $feed->owner_id = $userdata->ID;
  1480. $feed->save(false);
  1481. }
  1482. // Cron job for the update
  1483. $this->reschedule_cron();
  1484. }
  1485. function credits()
  1486. {
  1487. return 'Powered by <a href="http://www.enthropia.com/labs/wp-lifestream/">Lifestream</a>.';
  1488. }
  1489. /**
  1490. * Adds/updates the options on plug-in activation.
  1491. */
  1492. function install($allow_database_install=true)
  1493. {
  1494. $version = (string)$this->get_option('_version', 0);
  1495. if ($allow_database_install)
  1496. {
  1497. $this->install_database($version);
  1498. }
  1499. if (version_compare($version, '0.95', '<'))
  1500. {
  1501. foreach ($this->_options as $key=>$value)
  1502. {
  1503. $ovalue = get_option('lifestream_' . $key);
  1504. if (!$ovalue)
  1505. {
  1506. $value = $value;
  1507. }

Large files files are truncated, but you can click here to view the full file