limit) && !empty($this->total_count)) { if ($this->total_count > $this->limit) { jimport('joomla.html.pagination'); $pagination = new JPagination($this->total_count, $this->limitstart, $this->limit ); } } return $pagination; } function getReturnURLs(&$urls) { $jinput = JFactory::getApplication()->input; $option = $jinput->getCmd('option'); $urls = array(); $urls['data_sources'] = $jinput->getString('data_sources_return_url',str_replace('&','&',JRoute::_('index.php?option='.$option.'&task=viewDataSources&limit='.$this->limit.'&limitstart='.$this->limitstart))); $url = str_replace('&','&',JRoute::_('index.php?option='.$option.'&task=viewRulesetArchives')); $urls['archives'] = $url; } function loadDataSources($limit, $limitstart, &$error_msg) { $jinput = JFactory::getApplication()->input; $option = $jinput->getCmd('option'); $db = JFactory::getDbo(); $this->limit = $limit; $this->limitstart = $limitstart; if (!empty($limit)) { $query = 'SELECT id, tag, title, source_type, source_params, cache_type, cache_time FROM #__tabulizer_data_source LIMIT '.intval($limitstart).', '.intval($limit); } else { $query = 'SELECT id, tag, title, source_type, source_params, cache_type, cache_time FROM #__tabulizer_data_source'; } $db->setQuery($query); $rows = $db->loadObjectList(); if (empty($rows)) { return false; } else { $this->data_sources = $rows; $query = 'SELECT count(*) FROM #__tabulizer_data_source WHERE 1'; $db->setQuery($query); $this->total_count = $db->loadResult(); return true; } } function loadPublishingPreferences(&$error_msg) { $jinput = JFactory::getApplication()->input; $option = $jinput->getCmd('option'); $db = JFactory::getDbo(); if (!empty($this->data_source)) { $tag = $this->data_source->tag; } else { // this should never happen $error_msg = 'Data source is not loaded!'; return false; } $query = 'SELECT * FROM #__tabulizer_data_source_publishing_preferences WHERE tag = ' . $db->quote($tag); $db->setQuery($query); $row = $db->loadObject(); $this->publishing_preferences = $row; return true; } function getPublishingPreferences() { return $this->publishing_preferences; } function savePublishingPreferences($tag, &$error_msg) { $jinput = JFactory::getApplication()->input; $option = $jinput->getCmd('option'); $db = JFactory::getDbo(); $query = 'SELECT * FROM #__tabulizer_data_source_publishing_preferences WHERE tag = ' . $db->quote($tag); $db->setQuery($query); $row = $db->loadObject(); $status = $jinput->getInt('ds_status',0); $mode = $jinput->getString('ds_mode',null); $keyphrases = $jinput->getString('ds_keyphrases',null); if (!empty($row)) { $query = 'UPDATE #__tabulizer_data_source_publishing_preferences SET `status`='.$db->quote($status).', `mode`='.$db->quote($mode).', `keyphrases`='.$db->quote($keyphrases).' WHERE tag = ' . $db->quote($tag); } else { $query = 'INSERT INTO #__tabulizer_data_source_publishing_preferences (`tag`,`status`,`mode`,`keyphrases`) VALUES ('.$db->quote($tag).','.$db->quote($status).','.$db->quote($mode).','.$db->quote($keyphrases).')'; } return TabulizerDatabase::executeQuery($query, $error_msg); } function getDataSourceRequest($source_type, $field_prefix, &$error_msg) { TabulizerPath::requireLib('data_source','common'); return TabulizerDataSource::getRequestedParams($source_type, $field_prefix, $error_msg); } function getDataSources() { return $this->data_sources; } function loadDataSource($id = null, $tag = null) { $jinput = JFactory::getApplication()->input; $option = $jinput->getCmd('option'); $db = JFactory::getDbo(); if (isset($tag)) { $query = 'SELECT id, tag, title, source_type, source_params, cache_type, cache_time FROM #__tabulizer_data_source WHERE tag = '. $db->quote($tag); } else { $query = 'SELECT id, tag, title, source_type, source_params, cache_type, cache_time FROM #__tabulizer_data_source WHERE id = '. $db->quote($id); } $db->setQuery($query); $result = $db->loadObject(); if (!empty($result)) { $this->data_source = $result; return $result; } else { return false; } } function getDataSource() { return $this->data_source; } function importDataSource($data_source, &$errors) { TabulizerPath::requireLib('data_source','common'); // validate type $options = TabulizerDataSource::getSourceTypeLabel(); if (!array_key_exists($data_source['source_type'],$options)) { $errors[] = sprintf(JText::_('COM_TABULIZER_DATA_SOURCE_INVALID_TYPE'), $data_source['source_type']); return false; } // validate cache if ($data_source['cache_type'] != TABULIZER_DATA_SOURCE_CACHE_OFF) { if (empty($data_source['cache_time'])) $data_source['cache_type'] = TABULIZER_DATA_SOURCE_CACHE_OFF; else $data_source['cache_type'] = TABULIZER_DATA_SOURCE_CACHE_ON; } if (TabulizerDataSource::validateDataSourceParams($data_source['params'], $error_msg)) { TabulizerDataSource::encodeParams($data_source['source_type'], $data_source['params'], $source_params_str, $error_msg); $data_source['source_params'] = $source_params_str; return $this->saveDataSource($data_source, $errors); } else { $errors[] = $error_msg; return false; } } function importDataSourceArchive($filename, &$errors) { $contents = file_get_contents($filename); if (empty($contents)) return false; $p = xml_parser_create(); xml_parse_into_struct($p, $contents, $vals, $index); xml_parser_free($p); $data_source_open = false; $data_source = array(); foreach ($vals as $node) { switch ($node['tag']) { case 'DATASOURCE': if ($node['type'] == 'open') { $data_source = array(); if (!empty($node['attributes']['TITLE'])) { $data_source['title'] = trim($node['attributes']['TITLE']); } if (!empty($node['attributes']['TAG'])) { $data_source['tag'] = trim($node['attributes']['TAG']); } else { $data_source['tag'] = TabulizerString::generateRandomString(24); } if (!empty($node['attributes']['SOURCE_TYPE'])) { $data_source['source_type'] = strtolower(trim($node['attributes']['SOURCE_TYPE'])); } if (!empty($node['attributes']['CACHE_TYPE'])) { $data_source['cache_type'] = intval(trim($node['attributes']['CACHE_TYPE'])); } else { $data_source['cache_type'] = TABULIZER_DATA_SOURCE_DEFAULT_CACHE_TYPE; } if (!empty($node['attributes']['CACHE_TIME'])) { $data_source['cache_time'] = intval(trim($node['attributes']['CACHE_TIME'])); } else { $data_source['cache_time'] = TABULIZER_DATA_SOURCE_DEFAULT_CACHE_TIME; } if (isset($data_source['title']) && isset($data_source['source_type'])) { $data_source['params'] = array(); $data_source_open = true; } else { $data_source_open = false; } } else if ($node['type'] == 'close') { if ($data_source_open) { $this->importDataSource($data_source, $errors); $data_source_open = false; } } break; case 'PARAM': if ($data_source_open) { if ($node['type'] == 'complete') { $attributes = $node['attributes']; $attribute_key = empty($attributes['KEY'])?null:strtolower(trim($attributes['KEY'])); $attribute_value = isset($attributes['VALUE'])?trim($attributes['VALUE']):null; if (isset($attribute_key) && (isset($attribute_value))) { $data_source['params'][$attribute_key] = $attribute_value; } } } break; } } if (empty($errors)) return true; else return false; } function verifyCompatibility($data_source, &$error_msg) { TabulizerPath::requireLib('data_source','common'); if (!TabulizerDataSource::decodeParams($data_source['source_type'],$data_source['source_params'],$source_params,$error_msg)) { // this should never happen $error_msg = 'Invalid data source params at verifyCompatibility'; return false; } $server_side = false; if (!empty($source_params['server_side'])) $server_side = true; if ($server_side) { TabulizerPath::requireLib('ruleset','admin'); $loader = new Ruleset(); $ruleset = $loader->getRuleset($source_params['ruleset_name'],$source_params['ruleset_archive']); if (empty($ruleset)) { // this should never happen $error_msg = 'Invalid ruleset for data source at verifyCompatibility'; return false; } $split_rule = false; $pagination_rule = false; if (!empty($ruleset['rules'])) { foreach ($ruleset['rules'] as $rule) { if (!empty($rule['split'])) $split_rule = true; if (!empty($rule['pagination'])) $pagination_rule = true; } } if ($split_rule) { $error_msg = JText::_('COM_TABULIZER_INVALID_DATA_SOURCE_SERVER_SIDE_INCOMPATIBILITY_SPLIT'); return false; } if (!$pagination_rule) { $error_msg = JText::_('COM_TABULIZER_INVALID_DATA_SOURCE_SERVER_SIDE_INCOMPATIBILITY_PAGINATION'); return false; } } return true; } function saveDataSource($data_source, &$error_msg) { $db = JFactory::getDbo(); $new_entry = (empty($data_source['id']))?true:false; $cache_type = intval($data_source['cache_type']); if ($cache_type == TABULIZER_DATA_SOURCE_CACHE_OFF) { $cache_time = 'NULL'; } else { $cache_time = intval($data_source['cache_time']); if (empty($cache_time)) $cache_time = TABULIZER_DATA_SOURCE_DEFAULT_CACHE_TIME; } // compatibilty issues such as: server side + split, or server side and lack of pagination if (!$this->verifyCompatibility($data_source,$error_msg)) { return false; } if ($new_entry) { $query = 'INSERT INTO #__tabulizer_data_source (`tag`, `title`, `source_type`, `source_params`, `cache_type`, `cache_time`) VALUES ('.$db->quote($data_source['tag']).','.$db->quote($data_source['title']).','.$db->quote($data_source['source_type']).','.$db->quote($data_source['source_params']).','.$cache_type.','.$cache_time.')'; } else { $query = 'UPDATE #__tabulizer_data_source SET `title`='.$db->quote($data_source['title']).', `source_type`='.$db->quote($data_source['source_type']).', `source_params`='.$db->quote($data_source['source_params']). ', `cache_type`='.$cache_type.', `cache_time`='.$cache_time.' WHERE `id` = '.intval($data_source['id']); // remove cache contents $data_source_tags = array($data_source['tag']); $this->deleteDataSourceCache($data_source_tags); } return TabulizerDatabase::executeQuery($query, $error_msg); } function clearDataSourceCache($id, &$error_msg) { $db = JFactory::getDbo(); $query = 'SELECT tag FROM #__tabulizer_data_source WHERE id = '. intval($id); $db->setQuery($query); $data_source_tag = $db->loadResult(); if (!empty($data_source_tag)) { $this->deleteDataSourceImages($id); $data_source_tags = array($data_source_tag); return $this->deleteDataSourceCache($data_source_tags); } else return false; } function deleteDataSource($ids, &$error_msg) { $db = JFactory::getDbo(); $query = 'SELECT tag FROM #__tabulizer_data_source WHERE id IN ('.implode(',',$ids).')'; $db->setQuery($query); $data_source_tags = $db->loadColumn(); if ($data_source_tags) { $this->deleteDataSourceCache($data_source_tags); $query = 'DELETE FROM #__tabulizer_data_source WHERE id IN ('.implode(',',$ids).')'; return TabulizerDatabase::executeQuery($query, $error_msg); } } function deleteDataSourceCache($data_source_tags) { $db = JFactory::getDbo(); $tags = array(); foreach ($data_source_tags as $tag) { $tags[] = $db->quote($tag); } $query = 'SELECT cache_id FROM #__tabulizer_data_source_cache_key_map WHERE tag IN ('.implode(',',$tags).')'; $db->setQuery($query); $cache_ids = $db->loadColumn(); if (!empty($cache_ids)) { $query = 'DELETE FROM #__tabulizer_data_source_cache WHERE cache_id IN ('.implode(',',$cache_ids).')'; TabulizerDatabase::executeQuery($query, $error_msg); $query = 'DELETE FROM #__tabulizer_data_source_cache_properties WHERE cache_id IN ('.implode(',',$cache_ids).')'; TabulizerDatabase::executeQuery($query, $error_msg); } $query = 'DELETE FROM #__tabulizer_data_source_cache_key_map WHERE tag IN ('.implode(',',$tags).')'; return TabulizerDatabase::executeQuery($query, $error_msg); } function deleteDataSourceImages($data_source_id) { $data_source = $this->loadDataSource($data_source_id); if ($data_source->source_type == 'excel') { TabulizerPath::requireLib('data_source','common'); if (!TabulizerDataSource::decodeParams($data_source->source_type,$data_source->source_params,$params,$error_msg)) { // this should never happen $error_msg = 'Invalid data source params at verifyCompatibility'; return false; } $read_images = isset($params['read_images'])?$params['read_images']:false; if (!$read_images) return true; // nothing to do else { $image_tag = $data_source->tag; $image_prefix = 'tbl_' . $image_tag; $output_image_dir = TabulizerPath::getDirPath('sheet_images'); // traverse image directory for matches $image_files = scandir($output_image_dir); if (!empty($image_files)) { foreach ($image_files as $image_file) { if (strpos($image_file, $image_prefix)!==false) { $image_filepath = $output_image_dir . '/'. $image_file; @unlink($image_filepath); } } } } } } function addMergingTreeTag($nodes, &$merging_tree) { if (is_array($nodes)) { foreach ($nodes as $node) { if (is_array($node)) { $this->addMergingTreeTag($node, $merging_tree); } else { $merging_tree[] = $node; } } } } function exportDataSource($data_source, &$ds_merging_tree, &$ds_associated_files, &$ds_file_contents, &$error_msg) { if (!TabulizerDataSource::decodeParams($data_source->source_type, $data_source->source_params, $params, $errors)) { $error_msg = sprintf(JText::_('COM_TABULIZER_UNABLE_TO_DECODE_DATA_SROUCE_PARAMS'),$data_source->tag); return false; } $ds_file_contents .= ' title).'"'; if (!empty($data_source->tag)) $ds_file_contents .= ' tag="'.TabulizerString::makeXMLSafe($data_source->tag).'"'; $ds_file_contents .= ' source_type="'.TabulizerString::makeXMLSafe($data_source->source_type).'"'; $ds_file_contents .= ' cache_type="'.TabulizerString::makeXMLSafe($data_source->cache_type).'"'; if (!empty($data_source->cache_type)) { if ($data_source->cache_type != TABULIZER_DATA_SOURCE_CACHE_OFF) { $ds_file_contents .= ' cache_time="' . TabulizerString::makeXMLSafe($data_source->cache_time) . '"'; } } $ds_file_contents .= '>'."\n"; foreach ($params as $key => $value) { switch ($key) { case 'ruleset_archive': $associated_files = TabulizerRulesetAssociation::loadArchiveFiles($value); if ($associated_files) { $ds_associated_files = TabulizerRulesetAssociation::mergeAssociations($ds_associated_files,$associated_files); } break; case 'filepath': $associated_files = TabulizerRulesetAssociation::loadDataFile($value, $filename); if ($associated_files) { $ds_associated_files = TabulizerRulesetAssociation::mergeAssociations($ds_associated_files,$associated_files); $value = $filename; } break; case 'merging_tree': TabulizerPath::requireLib('merger_extraction','common'); $extractor = new MergerExtraction(); $nodes = $extractor->getMergingTree($value); if (!empty($nodes)) { $ds_merging_tree = array(); $this->addMergingTreeTag($nodes, $ds_merging_tree); } break; } $ds_file_contents .= ' '."\n"; } $ds_file_contents .= ' '."\n"; return true; } function exportDataSources($ids, &$error_msg) { TabulizerPath::requireLib('data_source','common'); $db = JFactory::getDbo(); $query = 'SELECT * FROM #__tabulizer_data_source WHERE id IN ('.implode(',',$ids).')'; $db->setQuery($query); $data_sources = $db->loadObjectList(); if (empty($data_sources)) { $error_msg = JText::_('COM_TABULIZER_UNABLE_TO_LOAD_SELECTED_DATA_SOURCES'); return false; } $ds_associated_files = array(); $ds_file_contents = ''."\n".'' . "\n"; $data_source = array_shift($data_sources); while ($data_source) { $ds_merging_tree = array(); if (!$this->exportDataSource($data_source, $ds_merging_tree, $ds_associated_files, $ds_file_contents, $error_msg)) return false; if (!empty($ds_merging_tree)) { $tags = array(); foreach ($ds_merging_tree as $tag) $tags[] = $db->quote($tag); $query = 'SELECT * FROM #__tabulizer_data_source WHERE tag IN ('.implode(',',$tags).')'; $db->setQuery($query); $data_sources_entries = $db->loadObjectList(); if (empty($data_sources_entries)) { foreach ($data_sources_entries as $data_source) { array_push($data_sources, $data_source); } } } $data_source = array_shift($data_sources); } $ds_file_contents .= ''; $archive_dir = TabulizerPath::getDirBase('temp'); $archive_filename = $archive_dir .DIRECTORY_SEPARATOR. 'ds_download.zip'; $ds_filename = 'ds_' . TabulizerString::generateRandomString() . '.xml'; $ds_filepath = $archive_dir .DIRECTORY_SEPARATOR. $ds_filename; if (file_put_contents($ds_filepath, $ds_file_contents)) { $associated_files = array('datasources'=>array($ds_filename=>$ds_filepath)); $ds_associated_files = TabulizerRulesetAssociation::mergeAssociations($ds_associated_files,$associated_files); } else { $error_msg = sprintf(JText::_('COM_TABULIZER_DATA_SOURCE_UNABLE_TO_WRITE_TEMP_EXPORT_FILE'),$ds_filepath); return false; } $zip = new ZipArchive; $return_code = $zip->open($archive_filename,ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE); if ($return_code === TRUE) { foreach ($ds_associated_files as $zipdir => $files) { if (empty($files)) continue; $zip->addEmptyDir($zipdir); foreach ($files as $filename => $filepath) { $zip->addFile($filepath, $zipdir .DIRECTORY_SEPARATOR. $filename); } } $zip->close(); } else { $error_desc = TabulizerUtils::getZipArchiveErrorDescription($return_code); $error_msg = sprintf(JText::_('COM_TABULIZER_DATA_FILE_ZIP_LIBRARY_MISSING'),$error_desc); return false; } // finally output the temp zip file header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Cache-Control: private', false); // required for certain browsers header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename="'. basename($archive_filename) . '";'); header('Content-Transfer-Encoding: binary'); header('Content-Length: ' . filesize($archive_filename)); ob_clean(); flush(); readfile($archive_filename); // remove temporary files @unlink($archive_filename); @unlink($ds_filepath); exit; } function loadDataFiles($limit = 0, $limitstart = 0) { TabulizerPath::requireLib('data_source','common'); $data_path = TabulizerPath::getDirPath('data'); $file2ds = array(); $this->loadDataSources(0,0,$error_msg); if (!empty($this->data_sources)) { foreach ($this->data_sources as $data_source) { $source_type = $data_source->source_type; $applicable_source_types = explode(',','csv,excel,html,rss'); if (in_array($source_type,$applicable_source_types)) { $title = $data_source->title; if (TabulizerDataSource::decodeParams($source_type,$data_source->source_params,$params,$error_msg)) { $id = $data_source->id; $return_url = '&data_sources_return_url='.urlencode(JFilterOutput::ampReplace ('index.php?option=com_tabulizer&task=viewDataFiles')); $link = ''.$title.''; if (isset($params['filepath'])) { if (file_exists($data_path .DIRECTORY_SEPARATOR. $params['filepath'])) { if (!isset($file2ds[$params['filepath']])) $file2ds[$params['filepath']] = array(); $file2ds[$params['filepath']][] = $link; } } } } } } $data_files = array(); $files = scandir($data_path); if (!empty($files)) { $allowed_extensions = explode(',',strtolower(ALLOWED_FILE_TYPES_FOR_DATA_IMPORTATION)); foreach ($files as $file) { $filepath = $data_path .DIRECTORY_SEPARATOR. $file; if (is_file($filepath)) { if (($file!='.')&&($file!='..')) { $parts = pathinfo($filepath); if (isset($parts['extension'])) { $extension = strtolower($parts['extension']); if (in_array($extension,$allowed_extensions)) { $linked_data_sources = ''; if (isset($file2ds[$file])) $linked_data_sources = implode("
\n", $file2ds[$file]); $data_files[$file] = array('modified'=>date("Y-m-d H:i:s.", filemtime($filepath)), 'linked_data_sources'=>$linked_data_sources); } } } } } } $this->data_files = $data_files; } function getDataFiles() { return $this->data_files; } function deleteDataFile($filenames, &$error_msg) { $this->loadDataFiles(); $data_path = realpath(TabulizerPath::getDirPath('data')); foreach ($filenames as $filename) { if (isset($this->data_files[$filename])) { $filepath = realpath($data_path .DIRECTORY_SEPARATOR. $filename); $base_path = pathinfo($filepath, PATHINFO_DIRNAME); if ($data_path != $base_path) { $error_msg = 'Invalid base path - please report this.'; return false; } else if (file_exists($filepath)) { @unlink($filepath); } } else { $error_msg = 'Invalid file selection:'.$filename. ' - make sure it exists in the data files directory and it has the proper extension.'; return false; } } return true; } function outputDataFiles($filenames, &$error_msg) { $this->loadDataFiles(); $data_path = realpath(TabulizerPath::getDirPath('data')); $archive_dir = $data_path; $archive_filename = $archive_dir .DIRECTORY_SEPARATOR. 'download.zip'; $zip = new ZipArchive; $return_code = $zip->open($archive_filename,ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE); if ($return_code === TRUE) { foreach ($filenames as $filename) { if (isset($this->data_files[$filename])) { $filepath = realpath($data_path .DIRECTORY_SEPARATOR. $filename); $base_path = pathinfo($filepath, PATHINFO_DIRNAME); if ($data_path != $base_path) { $error_msg = "Invalid base path $base_path for zip entry."; return false; } else if (file_exists($filepath)) { $zip->addFile($filepath, $filename); } else { $error_msg = "File not found: $filepath"; return false; } } else { $error_msg = 'Invalid file selection:'.$filename. ' - make sure it exists in the data files directory and it has the proper extension.'; return false; } } $zip->close(); } else { $error_desc = TabulizerUtils::getZipArchiveErrorDescription($return_code); $error_msg = sprintf(JText::_('COM_TABULIZER_DATA_FILE_ZIP_LIBRARY_MISSING'),$error_desc); return false; } // finally output the temp zip file header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Cache-Control: private', false); // required for certain browsers header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename="'. basename($archive_filename) . '";'); header('Content-Transfer-Encoding: binary'); header('Content-Length: ' . filesize($archive_filename)); ob_clean(); flush(); readfile($archive_filename); // remove temporary files @unlink($archive_filename); exit; } } ?>