PageRenderTime 54ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/system/expressionengine/third_party/transcribe/ext.transcribe.php

https://bitbucket.org/tdevonshire/hoolux
PHP | 1288 lines | 838 code | 236 blank | 214 comment | 154 complexity | 13307ed0d25a83b9e7054b6ef1dbe842 MD5 | raw file
  1. <?php if( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. require_once PATH_THIRD . 'transcribe/mod.transcribe.php';
  3. require_once PATH_THIRD . 'transcribe/libraries/Cache.php';
  4. class Transcribe_ext {
  5. public $name = 'Transcribe';
  6. public $version = '1.5';
  7. public $description = '';
  8. public $settings_exist = 'n';
  9. public $docs_url = '';
  10. public $settings = array();
  11. public $entry_sql;
  12. private $EE;
  13. private $site_id;
  14. public function __construct( $settings='' )
  15. {
  16. $this->EE =& get_instance();
  17. $this->transcribe = new Transcribe();
  18. $this->settings = $settings;
  19. $this->site_id = $this->EE->config->config['site_id'];
  20. }
  21. public function activate_extension()
  22. {
  23. $hooks['channel_entries_query_result'] = 'transcribe_channel_entries_query_results';
  24. $hooks['channel_entries_tagdata'] = 'transcribe_channel_entries_tagdata';
  25. $hooks['channel_module_create_pagination'] = 'transcribe_channel_module_create_pagination';
  26. $hooks['sessions_start'] = 'transcribe_session_start';
  27. $hooks['cp_menu_array'] = 'transcribe_cp_menu_array';
  28. $hooks['edit_entries_additional_where'] = 'transcribe_edit_entries_additional_where';
  29. // matrix hooks
  30. $hooks['matrix_data_query'] = 'transcribe_matrix_data_query';
  31. // playa hooks
  32. $hooks['playa_fetch_rels_query'] = 'transcribe_playa_fetch_rels_query';
  33. // structure hooks
  34. $hooks['structure_index_view_data'] = 'transcribe_structure_index_view_data';
  35. $hooks['structure_get_data_end'] = 'transcribe_structure_get_data_end';
  36. $hooks['structure_get_selective_data_results'] = 'transcribe_structure_get_selective_data_results';
  37. $hooks['structure_allow_dupes'] = 'transcribe_structure_allow_dupes';
  38. foreach ($hooks as $hook => $ext_method)
  39. {
  40. $this->EE->db->insert('extensions', array(
  41. 'class' => __CLASS__,
  42. 'method' => $ext_method,
  43. 'hook' => $hook,
  44. 'settings' => serialize($this->settings),
  45. 'priority' => 9,
  46. 'version' => $this->version,
  47. 'enabled' => 'y'
  48. ));
  49. }
  50. }
  51. /**
  52. * Extension at channel_entries_query_results hook
  53. *
  54. * Receives a query result of entries which we then modify to pull the
  55. * proper translation of the query result if they exist. If nothing exists
  56. * we return the query results with no change to what was passed into the
  57. * function.
  58. */
  59. public function transcribe_channel_entries_query_results( $object, $query_results )
  60. {
  61. $disable_transcribe = $this->EE->TMPL->fetch_param('transcribe');
  62. if( !empty($disable_transcribe) AND $disable_transcribe == 'disable' ) return $query_results;
  63. // is transcribe enabled for this site?
  64. $settings = $this->transcribe->_get_settings();
  65. if( empty($settings->enable_transcribe) ) return $query_results;
  66. // is_search boolean
  67. $is_search = FALSE;
  68. // get currently selected language
  69. $language_id = $this->transcribe->_set_current_language();
  70. $language_id = $language_id['id'];
  71. $search_id = $this->EE->uri->query_string;
  72. $pattern = '/\/.+/';
  73. $replacement = '';
  74. $search_id = preg_replace($pattern, $replacement, $search_id);
  75. if( !empty($this->EE->TMPL->module_data['Search']) )
  76. $search_result = $this->EE->db->get_where('search', array('search_id' => $search_id), 1)->row();
  77. $is_channel = strstr($object->EE->TMPL->tagproper, '{exp:channel:entries');
  78. // is this a search query?
  79. if( !empty($this->EE->TMPL->module_data['Search']) && !empty($search_result) && empty($is_channel) )
  80. {
  81. // the following is to get the first search results to display properly.
  82. // rewriting the search query here to only reflect entries from our current language.
  83. $search_query = unserialize(stripslashes($search_result->query));
  84. // check to see if the query has already been modified
  85. $already_modified = strstr($search_query, 'transcribe_entries_languages');
  86. if( $already_modified != FALSE && ($this->EE->pagination->cur_page == 1 || $this->EE->pagination->cur_page == 0) )
  87. {
  88. // This means we need to go aehad and filter the first results. All other pages are filtered base on the search query being changed in the pagination below.
  89. $is_search = TRUE;
  90. $search_result->query = unserialize(stripslashes($search_result->query));
  91. $object->sql = $search_result->query;
  92. $this->EE->session->set_cache('transcribe', 'entries_sql', $search_query);
  93. $current_count = count($query_results);
  94. $search_limit = "LIMIT $current_count";
  95. preg_match('/IN \(([0-9,]+)\)/', $search_result->query, $matches);
  96. $entry_ids = explode(',', $matches[1]);
  97. $all_entry_ids = array();
  98. foreach($entry_ids as $id) $all_entry_ids[]['entry_id'] = $id;
  99. // save ORDER BY for later use
  100. preg_match('/ORDER BY (.*)$/', $search_result->query, $matches);
  101. if( !empty($matches) )
  102. $order_by = $matches[1];
  103. if( !empty($_SESSION['search']) )
  104. {
  105. // don't love this approach, but due to the way the search module is built this is needed if we want our excerpts
  106. unset($_SESSION['search']);
  107. $url = $this->EE->functions->fetch_site_index(TRUE).$this->EE->uri->uri_string;
  108. $this->EE->functions->redirect($url);
  109. }
  110. }
  111. else
  112. {
  113. $object->pagination->page_links = NULL;
  114. $url = $this->EE->functions->fetch_site_index(1);
  115. // this injects the language segment when it's suppose to be present on pagination and autopath stuff.
  116. $object->pagination->basepath = $this->transcribe->_set_base($object->pagination->basepath);
  117. // return the results.. should be filtered from pagination code block below
  118. return $query_results;
  119. }
  120. }
  121. else
  122. {
  123. $this->EE->db->select('el.id', 1);
  124. $this->EE->db->from('transcribe_entries_languages as el');
  125. $this->EE->db->where_not_in('language_id ', 0);
  126. $query = $this->EE->db->get();
  127. if( $query->num_rows() == 0 )
  128. return $query_results;
  129. if( empty($this->entry_sql) AND !empty($object->sql) )
  130. {
  131. $this->EE->session->set_cache('transcribe', 'entries_sql', $object->sql);
  132. }
  133. // retrieve all entry_id's without the query limit (limit results after grabbing the translations)
  134. $current_queries = array_reverse($this->EE->db->queries);
  135. $select_entries_sql = NULL;
  136. foreach( $current_queries as $query )
  137. {
  138. // check for relationship
  139. if( strpos($query, 'SELECT rel_id, rel_parent_id, rel_child_id, rel_type, rel_data') !== FALSE )
  140. {
  141. return $query_results;
  142. }
  143. elseif( strpos($query, 'SELECT `rel_id`, `rel_parent_id`, `rel_child_id`, `rel_type`, `reverse_rel_data`' ) !== FALSE )
  144. {
  145. // we have a reverse relationship
  146. return $query_results;
  147. }
  148. elseif( (strpos($query, 'SELECT t.entry_id FROM ' . $this->EE->db->dbprefix('channel_titles') . ' AS t') !== FALSE) OR (strpos($query, 'SELECT DISTINCT(t.entry_id) FROM ' . $this->EE->db->dbprefix('channel_titles') . ' AS t') !== FALSE) )
  149. {
  150. // we have regular results
  151. // save LIMIT for use later
  152. preg_match('/LIMIT ([0-9,\s]+)$/', $query, $matches);
  153. if( !empty($matches) )
  154. {
  155. $limit = $matches[1];
  156. $values = explode(',', $matches[1]);
  157. $limit = array(
  158. 'offset' => trim($values[0]),
  159. 'limit' => trim($values[1]),
  160. );
  161. }
  162. // remove limit from query
  163. $select_entries_sql = preg_replace('/LIMIT [0-9,\s]+$/', '', $query);
  164. // save ORDER BY for later use
  165. preg_match('/ORDER BY (.*)$/', $select_entries_sql, $matches);
  166. if( !empty($matches) )
  167. $order_by = $matches[1];
  168. $all_entry_ids = $this->EE->db->query($select_entries_sql);
  169. $all_entry_ids = $all_entry_ids->result_array();
  170. break;
  171. }
  172. }
  173. }
  174. if( empty($all_entry_ids))
  175. {
  176. $query_results = $this->rewrite_channel_and_comment_urls($query_results, $language_id);
  177. return $query_results;
  178. }
  179. // cache all entry id's for later use
  180. $original_entry_ids = array();
  181. foreach( $all_entry_ids as $row )
  182. $original_entry_ids[] = $row['entry_id'];
  183. // get entry id's for all entries in this result set with the current language id
  184. $this->EE->db->select('el.entry_id');
  185. $this->EE->db->from('transcribe_entries_languages AS tel');
  186. $this->EE->db->join('transcribe_entries_languages AS el', 'el.relationship_id = tel.relationship_id', 'INNER');
  187. $this->EE->db->join('channel_titles as t', 't.entry_id = el.entry_id');
  188. $this->EE->db->join('channels as w', 'w.channel_id = t.channel_id', 'left');
  189. $this->EE->db->join('channel_data as wd', 'wd.entry_id = t.entry_id', 'left');
  190. $this->EE->db->join('members as m', 'm.member_id = t.author_id', 'left');
  191. $this->EE->db->join('member_data as md', 'md.member_id = m.member_id', 'left');
  192. $this->EE->db->where_in('tel.entry_id', $original_entry_ids);
  193. $this->EE->db->where('el.language_id', $language_id);
  194. $this->EE->db->order_by($order_by, '', FALSE);
  195. $this->EE->db->group_by('el.relationship_id');
  196. if( !empty($limit) )
  197. $this->EE->db->limit($limit['limit'], $limit['offset']);
  198. $new_ids = $this->EE->db->get();
  199. $new_ids = $new_ids->result();
  200. // build a new array of entry id's to re-run the channel entries query with the current language
  201. $entry_ids = array();
  202. foreach( $new_ids as $row )
  203. $entry_ids[] = $row->entry_id;
  204. // if there are no entries to select, return an empty result
  205. if( empty($entry_ids) )
  206. {
  207. // wow why was this so hard to do
  208. $object->return_data = $object->EE->TMPL->no_results;
  209. return array();
  210. }
  211. // modify the original query to get the correct entries for the current language
  212. $sql_split = preg_split('/IN \([0-9,]+\)/', $this->EE->session->cache['transcribe']['entries_sql']);
  213. $sql = $sql_split[0] . 'IN (' . implode(',', $entry_ids) . ')' . $sql_split[1];
  214. if( $is_search )
  215. {
  216. $sql .= ' '. $search_limit;
  217. $sql= str_replace('MDBMPREFIX', $this->EE->db->dbprefix, $sql);
  218. }
  219. $results = $this->EE->db->query($sql);
  220. $results = $results->result_array();
  221. $results = $this->rewrite_channel_and_comment_urls($results, $language_id);
  222. // pagination check
  223. if(!empty($object->enable['pagination']) && $object->enable['pagination'] == true )
  224. {
  225. $this->EE->db->select('COUNT(entry_id) AS count');
  226. $this->EE->db->from('transcribe_entries_languages');
  227. $this->EE->db->where_in('entry_id', $original_entry_ids);;
  228. $this->EE->db->where('language_id', $language_id);
  229. $entries_count = $this->EE->db->get();
  230. $entries_count = $entries_count->row();
  231. if( $this->EE->config->item('app_version') >= '240' )
  232. {
  233. // reset pagination links
  234. $object->pagination->page_links = NULL;
  235. $url = $this->EE->functions->fetch_site_index(1);
  236. // setup pagination for EE 2.4.0+
  237. $object->pagination->absolute_results = $entries_count->count;
  238. $object->pagination->total_rows = $entries_count->count;
  239. $object->EE->pagination->total_rows = $entries_count->count;
  240. //the following is to add support for next and prev linking
  241. $object->pagination->total_pages = $entries_count->count;
  242. //we run into an issue with EE adding an extra next page link based on logic thats already executed
  243. if($object->pagination->total_pages == $object->pagination->current_page)
  244. $object->pagination->page_next = '';
  245. // finally we build the pagination
  246. $object->pagination->build($entries_count->count, $sql);
  247. }
  248. else
  249. {
  250. // reset pagination links
  251. if( !empty($object->pagination_links) )
  252. $object->pagination_links = '';
  253. // setup pagination for Pre-EE 2.4.0
  254. $object->absolute_results = $entries_count->count;
  255. $object->total_rows = $entries_count->count;
  256. $object->EE->pagination->total_rows = $entries_count->count;
  257. $this->EE->pagination->total_rows = $entries_count->count;
  258. $object->create_pagination($entries_count->count);
  259. }
  260. }
  261. $language = $this->transcribe->_set_current_language();
  262. // check current langauge to see if we need to do dynamic field replacement
  263. // this needs to be at the top so we can get channel results on search results as well.
  264. if( is_array($object->cfields) && count($object->cfields) > 0 )
  265. {
  266. foreach($object->cfields[$this->site_id] as $name => $id)
  267. {
  268. $suffixes = strstr($name, "__");
  269. if( !empty($suffixes) )
  270. {
  271. $all_suffixes_string = array_values(array_filter(explode("__", $suffixes)));
  272. $all_suffixes = explode('_', $all_suffixes_string['0']);
  273. foreach($all_suffixes as $suffix)
  274. {
  275. if($suffix == $language['abbreviation'])
  276. {
  277. // add the changed filed to session cache so we can modify queries below (ie. matrix)
  278. $base_name = str_replace('__'.$all_suffixes_string['0'], '', $name);
  279. if( !empty($object->cfields[$this->site_id][$base_name]) )
  280. $changes[] = array($object->cfields[$this->site_id][$base_name] => $id);
  281. // assign the field id to the base tag name
  282. $object->cfields[$this->site_id][$base_name] = $id;
  283. }
  284. }
  285. }
  286. unset($suffixes);
  287. }
  288. //set changes to session var
  289. if( !empty($changes) )
  290. $this->EE->session->set_cache('transcribe', 'field_changes', $changes);
  291. }
  292. return $results;
  293. }
  294. /**
  295. * Extension at channel_entries_tagdata hook
  296. *
  297. * Modify the row's tagata by replacing variables that generate paths with
  298. * transcribe's uri path translator
  299. */
  300. public function transcribe_channel_entries_tagdata( $tagdata, $row, $object )
  301. {
  302. //checking to see if Transcribe is enabled for this site
  303. $settings = $this->transcribe->_get_settings();
  304. if( empty($settings->enable_transcribe) ) return $tagdata;
  305. // replace variable tag: url_title_path
  306. $tagdata = preg_replace("/\{url_title_path=\'([^']*)'\}/", "{exp:transcribe:uri path='$1'}{url_title}", $tagdata);
  307. // replace variable tag: entry_id_path
  308. $tagdata = preg_replace("/\{entry_id_path=\'([^']*)'\}/", "{exp:transcribe:uri path='$1'}{entry_id}", $tagdata);
  309. return $tagdata;
  310. }
  311. /**
  312. * Extension at channel_module_create_pagination hook
  313. *
  314. * Override the urls in $object to display the translated url for the
  315. * current language
  316. */
  317. public function transcribe_channel_module_create_pagination( $object )
  318. {
  319. // checking to see if Transcribe is enabled for this site
  320. $settings = $this->transcribe->_get_settings();
  321. if( empty($settings->enable_transcribe) ) return FALSE;
  322. // If SELF does not exists in site_index config item, set
  323. // site_index to empty. If the language abbreviation is there it
  324. // will auto-append SELF in the pagination library.
  325. $object->EE->config->config['site_index'] = (strpos($object->EE->config->config['site_index'], SELF) === FALSE) ? '' : $object->EE->config->config['site_index'];
  326. // is this a search query?
  327. if( !empty($this->EE->TMPL->module_data['Search']) )
  328. {
  329. $search_id = $this->EE->uri->query_string;
  330. $pattern = '/\/.+/';
  331. $replacement = '';
  332. $search_id = preg_replace($pattern, $replacement, $search_id);
  333. $search_result = $this->EE->db->get_where('search', array('search_id' => $search_id), 1)->row();
  334. if( !empty($search_result) )
  335. {
  336. // rewriting the search query here to only reflect entries from our current language.
  337. $search_query = unserialize(stripslashes($search_result->query));
  338. // check to see if the query has already been modified
  339. $already_modified = strstr($search_query, 'transcribe_entries_languages');
  340. if( $already_modified === FALSE )
  341. {
  342. // this means query is not modified and we can continue
  343. $search_parts = explode('WHERE', $search_query);
  344. $num_parts = count($search_parts);
  345. // this will only work when there is no subquery with a where clause... not an issue currently.
  346. if($num_parts == 2 && !empty($_SESSION['transcribe']['id']))
  347. {
  348. $transcribe_join = ' JOIN MDBMPREFIXtranscribe_entries_languages AS te ON t.entry_id = te.entry_id WHERE te.language_id = '.$_SESSION['transcribe']['id'];
  349. $new_search_query = $search_parts[0].$transcribe_join.' AND'.$search_parts[1];
  350. // get results to modify the number of pages for the initial results
  351. $sql = str_replace('MDBMPREFIX', 'exp_', $new_search_query);
  352. $query = $this->EE->db->query($sql);
  353. $object->total_rows = $query->num_rows();
  354. $new_search_query = addslashes(serialize($new_search_query));
  355. // query has now been rewritten, insert it into the db.
  356. $this->EE->db->where('search_id', $search_id);
  357. $this->EE->db->update('search', array('query' => $new_search_query));
  358. $_SESSION['search'] = TRUE;
  359. }
  360. }
  361. return false;
  362. }
  363. }
  364. // normal pagination
  365. $site_url = $this->EE->functions->fetch_site_index(0);
  366. $uri_string = $this->transcribe->_uri_reverse_lookup( str_replace($site_url, '', $object->basepath) );
  367. $object->basepath = $this->EE->functions->remove_double_slashes($site_url . '/' . $uri_string);
  368. }
  369. /**
  370. * Extension at session_start hook
  371. *
  372. * Process the url to load the proper template group and template name
  373. * depending on the current language or the language passed in the first
  374. * segment.
  375. */
  376. public function transcribe_session_start( $object )
  377. {
  378. if (REQ == 'CP') return FALSE;
  379. $this->EE->db->save_queries = TRUE;
  380. // variable to detect if were changing languages
  381. $switching_lang = $this->EE->input->get_post('lang', TRUE);
  382. // start session if it hasn't been already
  383. if( session_id() == '' ) session_start();
  384. // were going to need to do a str_replace on the url string before we explode the segments.
  385. $route = '';
  386. $segments = explode('/', $this->EE->uri->uri_string);
  387. // if the first segment is an abbreviation for a language, set as active language
  388. $is_abbreviation = $this->EE->db->get_where('transcribe_languages', array('abbreviation' => $segments[0]));
  389. $is_abbreviation = $is_abbreviation->row();
  390. //set the current lang details.
  391. if( !empty($is_abbreviation->abbreviation) )
  392. Cache::set(array('current_lang', $is_abbreviation->abbreviation), $is_abbreviation);
  393. // checking to see if Transcribe is enabled for this site
  394. // we might want to move this check to the top of the function eventually.
  395. $this->_get_transcribe_settings();
  396. if( empty($this->transcribe_settings->enable_transcribe) ) return FALSE;
  397. // translate URI segments for site_pages. Structure needs this corrected in order to pull the proper template
  398. $this->transcribe->_fix_structure_site_pages();
  399. // set language module wide with _set_current_language call
  400. if( empty($switching_lang) )
  401. {
  402. if( !empty($is_abbreviation->abbreviation) )
  403. {
  404. $current_language = $this->transcribe->_set_current_language($is_abbreviation->abbreviation);
  405. }
  406. else
  407. {
  408. $no_abbr_lang = $this->EE->config->item('transcribe_no_abbr');
  409. if( !empty($no_abbr_lang) )
  410. {
  411. if( is_array($no_abbr_lang) )
  412. {
  413. $no_abbr_lang = $no_abbr_lang[$this->EE->config->item('site_short_name')];
  414. }
  415. $current_language = $this->transcribe->_set_current_language($no_abbr_lang);
  416. }
  417. else
  418. {
  419. $current_language = $this->transcribe->_set_current_language();
  420. }
  421. }
  422. $this->EE->config->_global_vars['transcribe:language_abbreviation'] = $current_language['abbreviation'];
  423. }
  424. else
  425. {
  426. $current_language = $this->transcribe->_set_current_language($switching_lang);
  427. }
  428. // update url for Structure
  429. if( $structure_exists = $this->EE->db->table_exists('structure') )
  430. {
  431. $site_pages = $this->EE->config->item('site_pages');
  432. if( !empty($this->transcribe_settings->force_prefix) )
  433. {
  434. if( $this->transcribe_settings->force_prefix == 1 || ($this->transcribe_settings->force_prefix == 2 && !empty($current_language['force_prefix'])) )
  435. {
  436. $site_pages[$this->site_id]['url'] = $this->EE->uri->config->config['site_url'].'/'.$this->EE->config->config['site_index'];
  437. $site_pages[$this->site_id]['url'] = $this->EE->functions->remove_double_slashes($site_pages[$this->site_id]['url']);
  438. }
  439. }
  440. // removing all pages items for other languages here.
  441. $site_pages_entry_ids = array_keys($site_pages[$this->site_id]['uris']);
  442. $site_pages_entry_languages = $this->transcribe->_get_language($site_pages_entry_ids);
  443. if( empty($switching_lang) )
  444. {
  445. foreach($site_pages_entry_languages as $entry)
  446. {
  447. if( $entry['language_id']!= $current_language['id'] )
  448. {
  449. unset($site_pages[$this->site_id]['uris'][$entry['entry_id']]);
  450. unset($site_pages[$this->site_id]['templates'][$entry['entry_id']]);
  451. continue;
  452. }
  453. }
  454. $site_pages = $this->_get_related_structure_url($site_pages);
  455. $this->EE->config->set_item('site_pages', $site_pages);
  456. }
  457. else
  458. {
  459. $sql = array();
  460. $sql[] = "SELECT *";
  461. $sql[] = "FROM " . $this->EE->db->dbprefix('transcribe_languages');
  462. $sql[] = "WHERE (SELECT COUNT(*) FROM " . $this->EE->db->dbprefix('transcribe_entries_languages') . " WHERE language_id = " . $this->EE->db->dbprefix('transcribe_languages') . ".id) > 0";
  463. $languages = $this->EE->db->query(implode(' ', $sql))->result_array();
  464. foreach($languages as $row)
  465. {
  466. $site_pages = $this->EE->config->item('site_pages');
  467. // following foreach is from above... might want to make it a function
  468. foreach($site_pages_entry_languages as $entry)
  469. {
  470. if( $entry['language_id']!= $row['id'] )
  471. {
  472. unset($site_pages[$this->site_id]['uris'][$entry['entry_id']]);
  473. unset($site_pages[$this->site_id]['templates'][$entry['entry_id']]);
  474. continue;
  475. }
  476. }
  477. $pages = $this->_get_related_structure_url($site_pages);
  478. //reset site_pages
  479. $site_pages = $this->EE->config->item('site_pages');
  480. foreach($pages[$this->site_id]['uris'] as $key => $uri_string)
  481. {
  482. $site_pages[$this->site_id]['uris'][$key] = $uri_string;
  483. }
  484. $this->EE->config->set_item('site_pages', $site_pages);
  485. }
  486. }
  487. }
  488. if( !empty($is_abbreviation) ) array_shift($segments);
  489. // check to see if it's in the site_pages array (structure)
  490. $site_pages = $this->EE->config->item('site_pages');
  491. if( !empty($site_pages) AND in_array('/'.implode('/', $segments).'/', $site_pages[$this->site_id]['uris']) )
  492. {
  493. // removing the injected segment.
  494. $this->EE->uri->uri_string = (empty($segments) ? '' : '/' . implode('/', $segments));
  495. $this->EE->uri->segments = array();
  496. $this->EE->uri->rsegments = array();
  497. $this->EE->uri->_explode_segments();
  498. $this->EE->uri->_reindex_segments();
  499. return FALSE;
  500. }
  501. // check if a template exists for segment_1/segment_2
  502. if( !empty($segments) AND !empty($segments[1]) )
  503. {
  504. $route = $this->transcribe->_template_for_route( implode('/', array($segments[0], $segments[1])) );
  505. if( !empty($route) )
  506. $segments = array_slice($segments, 2);
  507. }
  508. // check if a template exists for segment_1
  509. if( empty($route) AND !empty($segments) )
  510. {
  511. $route = $this->transcribe->_template_for_route($segments[0]);
  512. if( !empty($route) )
  513. $segments = array_slice($segments, 1);
  514. }
  515. // check if a template exists for blank route (structure)
  516. $structure_installed = $this->EE->db->query('SHOW TABLES LIKE "%structure%"');
  517. $structure_installed = $structure_installed->num_rows();
  518. if( empty($route) && ( $structure_installed = 0) )
  519. {
  520. $route = $this->transcribe->_template_for_route('');
  521. }
  522. $this->EE->uri->uri_string = $route . (empty($segments) ? '' : '/' . implode('/', $segments));
  523. $this->EE->uri->segments = array();
  524. $this->EE->uri->rsegments = array();
  525. $this->EE->uri->_explode_segments();
  526. $this->EE->uri->_reindex_segments();
  527. }
  528. // STRUCTURE HOOK FUNCTIONS
  529. public function transcribe_structure_index_view_data( $data )
  530. {
  531. // checking to see if Transcribe is enabled for this site
  532. $settings = $this->transcribe->_get_settings();
  533. if( empty($settings->enable_transcribe) ) return $data;
  534. // get translations
  535. $sql = array();
  536. $sql[] = "SELECT *";
  537. $sql[] = "FROM " . $this->EE->db->dbprefix('transcribe_languages');
  538. $sql[] = "WHERE (SELECT COUNT(*) FROM " . $this->EE->db->dbprefix('transcribe_entries_languages') . " WHERE language_id = " . $this->EE->db->dbprefix('transcribe_languages') . ".id) > 0";
  539. $languages = $this->EE->db->query(implode(' ', $sql))->result();
  540. foreach($languages as $row)
  541. {
  542. $language_id = $row->id;
  543. $language_name = $row->name;
  544. $data['tabs']['transcribe-'.$language_id] = $language_name;
  545. if( !empty($data['data']['page-ui']) )
  546. {
  547. foreach($data['data']['page-ui'] as $key => $entry)
  548. {
  549. if( !empty($entry['language_id']) )
  550. if( $entry['language_id'] == $language_id )
  551. $data['data']['transcribe-'.$language_id][$key] = $entry;
  552. }
  553. }
  554. }
  555. unset($data['tabs']['page-ui']);
  556. return $data;
  557. }
  558. public function transcribe_structure_get_data_end( $data )
  559. {
  560. //checking to see if Transcribe is enabled for thie site
  561. $settings = $this->transcribe->_get_settings();
  562. if( empty($settings->enable_transcribe) ) return $data;
  563. // get only entry_id's
  564. $entry_ids = array();
  565. foreach($data as $row) $entry_ids[] = $row['entry_id'];
  566. if( !empty($entry_ids) )
  567. {
  568. $result = $this->EE->db->select('entry_id, language_id')->where_in('entry_id', $entry_ids)->get('transcribe_entries_languages')->result();
  569. if( !empty($result) )
  570. {
  571. foreach($result as $row)
  572. $data[$row->entry_id]['language_id'] = $row->language_id;
  573. foreach($data as $row)
  574. {
  575. if( empty($row['language_id']) && !empty($row['entry_id']) )
  576. unset($data[$row['entry_id']]);
  577. // if entry is a listing, make the associated entry also a listing (if associated)
  578. if( !empty($row['listing_cid']) && !empty($row['entry_id']) )
  579. {
  580. // find related entries
  581. $related_entries = $this->EE->db->select('tel2.entry_id, tel2.language_id')
  582. ->from('transcribe_entries_languages as tel')
  583. ->join('transcribe_entries_languages as tel2', 'tel2.relationship_id = tel.relationship_id', 'inner')
  584. ->where('tel.entry_id', $row['entry_id'])
  585. ->where('tel2.entry_id !=', $row['entry_id'])
  586. ->get()->result();
  587. foreach($related_entries as $entry)
  588. $data[$entry->entry_id]['listing_cid'] = $row['listing_cid'];
  589. }
  590. }
  591. }
  592. }
  593. return $data;
  594. }
  595. public function transcribe_structure_get_selective_data_results( $results )
  596. {
  597. //checking to see if Transcribe is enabled for thie site
  598. $settings = $this->transcribe->_get_settings();
  599. if( empty($settings->enable_transcribe) ) return $results;
  600. // get current language
  601. $language = $this->transcribe->_set_current_language();
  602. // get only entry_id's
  603. $entry_ids = array();
  604. foreach($results as $row) $entry_ids[] = $row['entry_id'];
  605. if( !empty($entry_ids) )
  606. {
  607. $result = $this->EE->db->select('entry_id, language_id')->where_in('entry_id', $entry_ids)->where('language_id', $language['id'])->get('transcribe_entries_languages')->result();
  608. $result_entry_ids = array();
  609. foreach($result as $row) $result_entry_ids[] = $row->entry_id;
  610. if( !empty($result) )
  611. {
  612. foreach($results as $key => $row)
  613. {
  614. if( $key != 0 AND !in_array($row['entry_id'], $result_entry_ids) )
  615. unset($results[$key]);
  616. }
  617. }
  618. }
  619. return $results;
  620. }
  621. //*********************************
  622. //** Allow dups function will return true if we can allow this url to be a duplicate
  623. //*********************************
  624. public function transcribe_structure_allow_dupes($uri)
  625. {
  626. // return true if this url hasn't been used in this language yet.
  627. // we get passed in the uri for the current entry
  628. $return = TRUE;
  629. $site_pages = $this->EE->config->item('site_pages');
  630. $lang_id = $this->EE->input->post('transcribe__transcribe_language');
  631. // removing all pages items for other languages here.
  632. $site_pages_entry_ids = array_keys($site_pages[$this->site_id]['uris']);
  633. $site_pages_entry_languages = $this->transcribe->_get_language($site_pages_entry_ids);
  634. if( !empty($lang_id) )
  635. {
  636. foreach($site_pages_entry_languages as $entry)
  637. {
  638. if( $entry['language_id']!= $lang_id )
  639. {
  640. unset($site_pages[$this->site_id]['uris'][$entry['entry_id']]);
  641. unset($site_pages[$this->site_id]['templates'][$entry['entry_id']]);
  642. continue;
  643. }
  644. }
  645. }
  646. // check the uri to see if we already have it in this langauge
  647. // if we do, we'll go ahead and return false
  648. // otherwise we'll return true
  649. foreach($site_pages[$this->site_id]['uris'] as $pages_uri)
  650. if($pages_uri == $uri)
  651. $return = FALSE;
  652. return $return;
  653. }
  654. public function transcribe_matrix_data_query($object, $params, $sql, $select_mode)
  655. {
  656. if (REQ == 'CP') return $this->EE->db->query($sql);
  657. //checking to see if Transcribe is enabled for thie site
  658. $settings = $this->transcribe->_get_settings();
  659. if( empty($settings->enable_transcribe) ) return $this->EE->db->query($sql);
  660. // remove all whitspace and new lines
  661. $sql = preg_replace('/\s\s+/', ' ', $sql);
  662. $changes = $this->EE->session->cache('transcribe', 'field_changes');
  663. //grab matrix changes from last call
  664. $matrix_changes = $this->EE->session->cache('transcribe', 'matrix_col_changes');
  665. if(!empty($changes))
  666. {
  667. foreach($changes as $change)
  668. {
  669. foreach($change as $orignal_field_id => $new_field_id)
  670. {
  671. if( $orignal_field_id == $object->field_id )
  672. {
  673. $object->field_id = $new_field_id;
  674. // loop through tha matrix fields for our current site
  675. foreach( $object->cache['fields'][$this->site_id] as $field)
  676. {
  677. if( $orignal_field_id == $field['field_id'] )
  678. {
  679. // get the col_ids to replace
  680. // we already have the field ids to replace from our session var
  681. $col_ids_to_change[$orignal_field_id] = $field['field_settings']['col_ids'];
  682. }
  683. if( $new_field_id == $field['field_id'])
  684. {
  685. // now were going to get the new col_ids
  686. $col_ids_to_use[$orignal_field_id] = $field['field_settings']['col_ids'];
  687. $old_field_id_to_use = $orignal_field_id;
  688. $new_field_id_to_use = $new_field_id;
  689. // modify the query.
  690. // we'll need to go ahead and modify the query to grab the data from the other matrix
  691. $sql = str_replace('field_id = '.$old_field_id_to_use, 'field_id = '.$new_field_id_to_use, $sql);
  692. $object->field_id = $new_field_id_to_use;
  693. // order gratest to least
  694. arsort($col_ids_to_change[$old_field_id_to_use]);
  695. // assign changes to arrays... will be asigned to a cache var later
  696. foreach($col_ids_to_change as $id => $col_changes)
  697. $matrix_changes['col_ids_to_change'][$id] = $col_changes;
  698. foreach($col_ids_to_use as $id => $col_changes)
  699. $matrix_changes['col_ids_to_use'][$id] = $col_changes;
  700. $matrix_changes['fields'][$new_field_id_to_use] = $old_field_id_to_use;
  701. foreach($col_ids_to_change[$old_field_id_to_use] as $col_id => $replace_id)
  702. {
  703. // the following code is left in and commented out for debugging if need be.
  704. // $sql_before = $sql;
  705. // echo $sql_before;
  706. $sql = preg_replace("/\scol_id_$replace_id(\s|,)/",' col_id_'.$col_ids_to_use[$old_field_id_to_use][$col_id].' as col_id_'.$replace_id.'$1', $sql);
  707. // $sql = str_replace(' col_id_'.$replace_id, ' col_id_'.$col_ids_to_use[$old_field_id_to_use][$col_id].' as col_id_'.$replace_id, $sql);
  708. // echo "SQL BEFORE: $sql_before";
  709. // echo "\n";
  710. // echo 'SEARCH: col_id_'.$replace_id.',';
  711. // echo "\n";
  712. // echo 'REPLACE: col_id_'.$col_ids_to_use[$old_field_id_to_use][$col_id].' as col_id_'.$replace_id;
  713. // echo "\n";
  714. // echo "SQL AFTER: $sql";
  715. // echo "\n\n\n\n\n\n\n";
  716. }
  717. }
  718. }
  719. }
  720. }
  721. }
  722. }
  723. // asign matrix col changes to cache
  724. if(!empty($matrix_changes))
  725. $this->EE->session->set_cache('transcribe', 'matrix_col_changes', $matrix_changes);
  726. return $this->EE->db->query($sql);
  727. }
  728. public function transcribe_playa_fetch_rels_query($object, $sql, $data = array())
  729. {
  730. if (REQ == 'CP') return $this->EE->db->query($sql);
  731. //checking to see if Transcribe is enabled for thie site
  732. $settings = $this->transcribe->_get_settings();
  733. if( empty($settings->enable_transcribe) ) return $this->EE->db->query($sql);
  734. // get cached changes
  735. $changes = $this->EE->session->cache('transcribe', 'matrix_col_changes');
  736. // clearn up the query from the hook
  737. $sql = preg_replace('/\s\s+/', ' ', $sql);
  738. if( !empty($data['field_ids']))
  739. {
  740. foreach($data['field_ids'] as $id => $field_id)
  741. {
  742. if( !empty($changes['fields'][$field_id]) )
  743. {
  744. $current_field_id =& $changes['fields'][$field_id];
  745. foreach($changes['col_ids_to_change'][$current_field_id] as $id => $replace_id)
  746. {
  747. // the following code is left in and commented out for debugging if need be.
  748. // $sql_before = $sql;
  749. $sql = str_replace('parent_col_id = '.$replace_id.' ', 'parent_col_id = '.$changes['col_ids_to_use'][$current_field_id][$id].' ', $sql);
  750. // echo "SQL BEFORE: $sql_before";
  751. // echo "\n";
  752. // echo 'SEARCH: parent_col_id = "'.$replace_id.'" ';
  753. // echo "\n";
  754. // echo 'REPLACE: parent_col_id = "'.$changes['col_ids_to_use'][$current_field_id][$id].'" ';
  755. // echo "\n";
  756. // echo "SQL AFTER: $sql";
  757. // echo "\n\n\n\n\n\n\n";
  758. }
  759. }
  760. }
  761. }
  762. return $this->EE->db->query($sql);
  763. }
  764. /**
  765. * Removes URL parameters from the url before processing segments
  766. */
  767. private function _remove_params()
  768. {
  769. $pattern = '/[\?|\&].*$/';
  770. preg_match($pattern, $this->EE->uri->uri_string, $matches);
  771. $this->url_params = (isset($matches[0])) ? $matches[0] : '';
  772. $this->EE->uri->uri_string = preg_replace($pattern, '', $this->EE->uri->uri_string);
  773. }
  774. /**
  775. * Restores URL parameters to the url after processing segments
  776. */
  777. private function _restore_params()
  778. {
  779. $this->EE->uri->uri_string .= $this->url_params;
  780. }
  781. public function update_extension( $current='' )
  782. {
  783. if( $current == '' OR $current == $this->version )
  784. {
  785. return FALSE;
  786. }
  787. if( $current < '1.1')
  788. {
  789. $hooks['channel_entries_row'] = 'transcribe_channel_entries_row';
  790. }
  791. if($current < '1.1.1')
  792. {
  793. $hooks['matrix_data_query'] = 'transcribe_matrix_data_query';
  794. $remove_extension[] = 'transcribe_channel_entries_row';
  795. }
  796. if($current < '1.1.1.1')
  797. {
  798. $hooks['playa_fetch_rels_query'] = 'transcribe_playa_fetch_rels_query';
  799. }
  800. if($current < '1.1.1.2')
  801. {
  802. if( $this->EE->config->item('app_version') >= '240' )
  803. {
  804. $hooks['cp_menu_array'] = 'transcribe_cp_menu_array';
  805. $hooks['edit_entries_additional_where'] = 'transcribe_edit_entries_additional_where';
  806. }
  807. }
  808. if($current < '1.1.1.3')
  809. {
  810. $hooks['structure_allow_dupes'] = 'transcribe_structure_allow_dupes';
  811. }
  812. if(!empty($hooks))
  813. {
  814. foreach ($hooks as $hook => $ext_method)
  815. {
  816. $this->EE->db->insert('extensions', array(
  817. 'class' => __CLASS__,
  818. 'method' => $ext_method,
  819. 'hook' => $hook,
  820. 'settings' => serialize($this->settings),
  821. 'priority' => 9,
  822. 'version' => $this->version,
  823. 'enabled' => 'y'
  824. ));
  825. }
  826. }
  827. if(!empty($remove_extension))
  828. {
  829. foreach( $remove_extension as $method)
  830. {
  831. $this->EE->db->where('method', $method);
  832. $this->EE->db->delete('extensions');
  833. }
  834. }
  835. $this->EE->db->where('class', __CLASS__);
  836. $this->EE->db->update('extensions', array('version' => $this->version));
  837. }
  838. public function disable_extension()
  839. {
  840. $this->EE->db->where('class', __CLASS__);
  841. $this->EE->db->delete('extensions');
  842. }
  843. //this funnction used to rewrite the comment and channel urls for use in the templates
  844. private function rewrite_channel_and_comment_urls($results, $language_id)
  845. {
  846. $force = $this->transcribe->_get_settings();
  847. $language = $this->EE->db->get_where('transcribe_languages', array('id' => $language_id));
  848. $language = $language->row_array();
  849. if( !empty($force->force_prefix))
  850. {
  851. if( $force->force_prefix == 1 || ($force->force_prefix == 2 && !empty($language['force_prefix'])) )
  852. {
  853. foreach( $results as $key => $row)
  854. {
  855. $site_url = $this->EE->config->item('site_url');
  856. // channel_url
  857. $results[$key]['channel_url'] = str_replace($site_url, $site_url.$language['abbreviation'].'/', $results[$key]['channel_url']);
  858. $results[$key]['channel_url'] = $this->EE->functions->remove_double_slashes($results[$key]['channel_url']);
  859. // comment_url
  860. $results[$key]['comment_url'] = str_replace($site_url, $site_url.$language['abbreviation'].'/', $results[$key]['comment_url']);
  861. $results[$key]['comment_url'] = $this->EE->functions->remove_double_slashes($results[$key]['channel_url']);
  862. // search_results_url
  863. if( !empty($results[$key]['search_results_url']) )
  864. {
  865. $results[$key]['search_results_url'] = str_replace($site_url, $site_url.$language['abbreviation'].'/', $results[$key]['search_results_url']);
  866. $results[$key]['search_results_url'] = $this->EE->functions->remove_double_slashes($results[$key]['search_results_url']);
  867. }
  868. }
  869. }
  870. }
  871. return $results;
  872. }
  873. /*
  874. * This function takes the current listing parent url and if it's not in the current language it will go ahead and
  875. * grab the coorosponding URL for the listing in the current language.
  876. */
  877. private function _get_related_structure_url($site_pages)
  878. {
  879. $language = $this->transcribe->_set_current_language();
  880. $lang_abbr = $language['abbreviation'];
  881. $language_id = $language['id'];
  882. $listing_data = $this->EE->db->select('*')
  883. ->where('site_id', $this->site_id)->get('structure_listings');
  884. $listing_data = $listing_data->result_array();
  885. $site_pages_orignal = $this->EE->config->item('site_pages');
  886. // getting relationship ids in 2 foreach loops so we have a lighter query
  887. foreach($listing_data as $listing)
  888. {
  889. $ids[] = $listing['entry_id'];
  890. $ids[] = $listing['parent_id'];
  891. }
  892. // get more ids and set the language abbreviation segment to /
  893. foreach($site_pages[$this->site_id]['uris'] as $key => $string)
  894. {
  895. $ids[] = $key;
  896. if( $string == '/'.$lang_abbr )
  897. $site_pages[$this->site_id]['uris'][$key] = '/';
  898. }
  899. if(!empty($ids))
  900. {
  901. $ids = array_unique($ids);
  902. $ids = implode(',', $ids);
  903. $this->EE->db->select('entry_id, relationship_id, language_id');
  904. $this->EE->db->where_in($ids);
  905. $relationships = $this->EE->db->get('transcribe_entries_languages');
  906. $relationships = $relationships->result_array();
  907. //setting relationship data
  908. foreach($relationships as $relationship)
  909. $rel_data[$relationship['entry_id']] = $relationship;
  910. // get the current parent id
  911. foreach($listing_data as $listing)
  912. {
  913. foreach($relationships as $rel)
  914. {
  915. if( $rel['entry_id'] == $listing['parent_id'] && empty($x) )
  916. {
  917. // we now have the current parent id... but this doesn't mean that the entry is the correct langage
  918. $current_parent['entry_id'] = $listing['parent_id'];
  919. $current_parent['rel'] = $rel['relationship_id'];
  920. break;
  921. }
  922. }
  923. // loop through relationships again and grab the entry_ids that we need to check for
  924. foreach($relationships as $rel)
  925. {
  926. // get the entry ids we need here
  927. if( $rel['relationship_id'] == $current_parent['rel'])
  928. {
  929. //we have a match is it in our current language?
  930. if( !empty($site_pages[$this->site_id]['uris'][$rel['entry_id']]) )
  931. {
  932. //this is the segemnt we want to replace with
  933. $replace_with[$rel['entry_id']]['rel'] = $rel['relationship_id'];
  934. $replace_with[$rel['entry_id']]['uri'] = $site_pages[$this->site_id]['uris'][$rel['entry_id']];
  935. break;
  936. }
  937. }
  938. }
  939. }
  940. if(!empty($replace_with))
  941. {
  942. foreach($replace_with as $listing_parent)
  943. {
  944. // get the segemnts we need to replace
  945. foreach($relationships as $rel)
  946. {
  947. if( $rel['relationship_id'] == $listing_parent['rel'] )
  948. {
  949. $segments_to_replace[$rel['entry_id']] = $site_pages_orignal[$this->site_id]['uris'][$rel['entry_id']];
  950. }
  951. }
  952. foreach($listing_data as $listing)
  953. {
  954. // is the listing in our current language?
  955. if(!empty($site_pages[$this->site_id]['uris'][$listing['entry_id']]))
  956. {
  957. //if so lets go ahead and get rid of the segments to replace
  958. foreach($segments_to_replace as $replace_entry_id => $replace_string)
  959. {
  960. //check to make sure it's not in our current language
  961. if( empty($site_pages[$this->site_id]['uris'][$replace_entry_id] ) )
  962. {
  963. // is this a listing on the home page?
  964. if($listing_parent['uri'] == '/')
  965. $site_pages[$this->site_id]['uris'][$listing['entry_id']] = str_replace($replace_string, '', $site_pages[$this->site_id]['uris'][$listing['entry_id']]);
  966. else
  967. $site_pages[$this->site_id]['uris'][$listing['entry_id']] = str_replace($replace_string, $listing_parent['uri'], $site_pages[$this->site_id]['uris'][$listing['entry_id']]);
  968. }
  969. }
  970. }
  971. }
  972. }
  973. }
  974. }
  975. return $site_pages;
  976. }
  977. private function _get_transcribe_settings()
  978. {
  979. $this->transcribe_settings = $this->transcribe->_get_settings();
  980. }
  981. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  982. # Hooks for Adding "Filter by Language" in Content Edit Screen #
  983. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  984. # #
  985. # Credit where credit is due: #
  986. # The basis of this technique was published by Rob Sanchez #
  987. # in March 2012 - https://github.com/rsanchez/filter_by_author #
  988. # #
  989. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  990. /**
  991. * Checks for a language ID and retrieves a list of related entry_ids which are added as a where_in clause
  992. *
  993. * @author Bryan Nielsen
  994. * @param array $filter_data the original filter data from the search query
  995. * @return array addtional wheres for the query
  996. */
  997. public function transcribe_edit_entries_additional_where($filter_data)
  998. {
  999. $_hook_wheres = $this->EE->extensions->last_call;
  1000. if ($this->EE->input->post('language_id'))
  1001. {
  1002. // Run query and get entry ids that are in requested language id
  1003. // Then add where_in clause with those entry ids
  1004. $query = $this->EE->db->select('entry_id')->get_where('transcribe_entries_languages', array('language_id' => $this->EE->input->post('language_id')));
  1005. if($query->num_rows() > 0) {
  1006. $entry_ids = array();
  1007. foreach($query->result() as $row)
  1008. {
  1009. $entry_ids[] = $row->entry_id;
  1010. }
  1011. $_hook_wheres['entry_id'] = $entry_ids;
  1012. }
  1013. }
  1014. return $_hook_wheres;
  1015. }
  1016. /**
  1017. * Adds the Filter by language dropdown to the edit entries screen via JS
  1018. *
  1019. * @author Bryan Nielsen
  1020. * @param array $menu the menu array
  1021. * @return array the menu array
  1022. */
  1023. public function transcribe_cp_menu_array($menu)
  1024. {
  1025. if ($this->EE->extensions->last_call !== FALSE)
  1026. {
  1027. $menu = $this->EE->extensions->last_call;
  1028. }
  1029. //confirm we're on the edit entries screen
  1030. if ($this->EE->input->get('C') === 'content_edit' && ! $this->EE->input->get('M') && $this->EE->config->item('app_version') >= '240' )
  1031. {
  1032. $this->EE->load->library('javascript');
  1033. $this->EE->lang->loadfile('transcribe');
  1034. $languages = array('' => lang('transcribe_select_language_default'));
  1035. //get list of available languages
  1036. $query = $this->EE->db->select('id, name')->get('transcribe_languages');
  1037. foreach ($query->result() as $row)
  1038. {
  1039. $languages[$row->id] = $row->name;
  1040. }
  1041. //add the dropdown filter
  1042. $this->EE->javascript->output('
  1043. $("form#filterform div.group").append('.$this->EE->javascript->generate_json(NBS.NBS.form_dropdown('language_id', $languages, NULL, 'id="language_id"')).');
  1044. $("#language_id").on("change", function() {
  1045. $("#search_button").trigger("click");
  1046. });
  1047. ');
  1048. }
  1049. return $menu;
  1050. }
  1051. }
  1052. /* End of File: ext.transcribe.php */