mirror of https://github.com/MISP/MISP
First bash at Taxonomies
What works: - added submodules for taxonomies - added import tool for taxonomies - added models and convenience functions for taxonomies - site admins can update taxonomy libraries - list taxonomies / view indvidual ones (with all resolved tags) - create tags manually if a taxonomy is enabled - view related tags / events quickly from the Taxonomy view What doesn't work: - Users still cannot choose a tag from taxonomy lists (this will be the main functionality) - Feature cannot be disabledpull/762/head
parent
c5ef4e1d2d
commit
3784209cf5
|
@ -31,7 +31,6 @@
|
|||
!/app/files/empty
|
||||
/app/files/terms/*
|
||||
!/app/files/terms/empty
|
||||
!/app/files/taxonomies
|
||||
/app/webroot/img/logo.png
|
||||
/app/webroot/img/custom/*
|
||||
!/app/webroot/img/custom/empty
|
||||
|
|
|
@ -6,3 +6,6 @@
|
|||
path = PyMISP
|
||||
url = https://github.com/MISP/PyMISP.git
|
||||
branch = master
|
||||
[submodule "app/files/taxonomies"]
|
||||
path = app/files/taxonomies
|
||||
url = https://github.com/MISP/misp-taxonomies.git
|
||||
|
|
|
@ -560,6 +560,39 @@ CREATE TABLE IF NOT EXISTS `whitelist` (
|
|||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `taxonomies` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`namespace` varchar(255) COLLATE utf8_bin NOT NULL,
|
||||
`description` text COLLATE utf8_bin NOT NULL,
|
||||
`version` int(11) NOT NULL,
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `taxonomy_entries` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`taxonomy_predicate_id` int(11) NOT NULL,
|
||||
`value` text COLLATE utf8_bin NOT NULL,
|
||||
`expanded` text COLLATE utf8_bin NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `taxonomy_predicate_id` (`taxonomy_predicate_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `taxonomy_predicates` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`taxonomy_id` int(11) NOT NULL,
|
||||
`value` text COLLATE utf8_bin NOT NULL,
|
||||
`expanded` text COLLATE utf8_bin NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `taxonomy_id` (`taxonomy_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Default values for initial installation
|
||||
--
|
||||
|
|
|
@ -111,4 +111,38 @@ CREATE TABLE IF NOT EXISTS `sharing_groups` (
|
|||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `taxonomies` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`namespace` varchar(255) COLLATE utf8_bin NOT NULL,
|
||||
`description` text COLLATE utf8_bin NOT NULL,
|
||||
`version` int(11) NOT NULL,
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `taxonomy_entries` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`taxonomy_predicate_id` int(11) NOT NULL,
|
||||
`value` text COLLATE utf8_bin NOT NULL,
|
||||
`expanded` text COLLATE utf8_bin NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `taxonomy_predicate_id` (`taxonomy_predicate_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `taxonomy_predicates` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`taxonomy_id` int(11) NOT NULL,
|
||||
`value` text COLLATE utf8_bin NOT NULL,
|
||||
`expanded` text COLLATE utf8_bin NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `taxonomy_id` (`taxonomy_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
|
|
|
@ -89,6 +89,18 @@ class TagsController extends AppController {
|
|||
}
|
||||
}
|
||||
|
||||
public function quickAdd() {
|
||||
if ((!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) || !$this->request->is('post')) throw new NotFoundException('You don\'t have permission to do that.');
|
||||
debug($this->request->data);
|
||||
if (isset($this->request->data['Tag']['request'])) $this->request->data['Tag'] = $this->request->data['Tag']['request'];
|
||||
if ($this->Tag->quickAdd($this->request->data['Tag']['name'])) {
|
||||
$this->Session->setFlash('The tag has been saved.');
|
||||
} else {
|
||||
$this->Session->setFlash('The tag could not be saved. Please, try again.');
|
||||
}
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
|
||||
public function edit($id) {
|
||||
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) {
|
||||
throw new NotFoundException('You don\'t have permission to do that.');
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
<?php
|
||||
App::uses('AppController', 'Controller');
|
||||
|
||||
class TaxonomiesController extends AppController {
|
||||
public $components = array('Session', 'RequestHandler');
|
||||
|
||||
public function beforeFilter() {
|
||||
parent::beforeFilter();
|
||||
}
|
||||
|
||||
public $paginate = array(
|
||||
'limit' => 60,
|
||||
'maxLimit' => 9999, // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
|
||||
'order' => array(
|
||||
'Taxonomy.id' => 'DESC'
|
||||
),
|
||||
);
|
||||
|
||||
public function index() {
|
||||
$taxonomies = $this->Taxonomy->listTaxonomies();
|
||||
$this->paginate['recursive'] = -1;
|
||||
$this->set('taxonomies', $this->paginate());
|
||||
}
|
||||
|
||||
public function view($id) {
|
||||
if (isset($this->passedArgs['pages'])) $currentPage = $this->passedArgs['pages'];
|
||||
else $currentPage = 1;
|
||||
$urlparams = '';
|
||||
$passedArgs = array();
|
||||
App::uses('CustomPaginationTool', 'Tools');
|
||||
$customPagination = new CustomPaginationTool();
|
||||
$params = $customPagination->createPaginationRules($events, $this->passedArgs, $this->alias);
|
||||
$this->params->params['paging'] = array($this->modelClass => $params);
|
||||
$taxonomy = $this->Taxonomy->getTaxonomy($id, array('full' => true));
|
||||
$customPagination->truncateByPagination($taxonomy['entries'], $params);
|
||||
$this->set('entries', $taxonomy['entries']);
|
||||
$this->set('taxonomy', $taxonomy['Taxonomy']);
|
||||
}
|
||||
|
||||
public function enable($id) {
|
||||
if (!$this->_isSiteAdmin() || !$this->request->is('Post')) throw new MethodNotAllowedException('You don\'t have permission to do that.');
|
||||
$taxonomy = $this->Taxonomy->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('Taxonomy.id' => $id),
|
||||
));
|
||||
$taxonomy['Taxonomy']['enabled'] = true;
|
||||
$this->Taxonomy->save($taxonomy);
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Taxonomy',
|
||||
'model_id' => $id,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'enable',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Taxonomy enabled',
|
||||
'change' => $taxonomy['Taxonomy']['namespace'] . ' - enabled',
|
||||
));
|
||||
$this->Session->setFlash('Taxonomy enabled.');
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
|
||||
public function disable($id) {
|
||||
if (!$this->_isSiteAdmin() || !$this->request->is('Post')) throw new MethodNotAllowedException('You don\'t have permission to do that.');
|
||||
$taxonomy = $this->Taxonomy->find('first', array(
|
||||
'recursive' => -1,
|
||||
'conditions' => array('Taxonomy.id' => $id),
|
||||
));
|
||||
$taxonomy['Taxonomy']['enabled'] = false;
|
||||
$this->Taxonomy->save($taxonomy);
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Taxonomy',
|
||||
'model_id' => $id,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'disable',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Taxonomy disabled',
|
||||
'change' => $taxonomy['Taxonomy']['namespace'] . ' - disabled',
|
||||
));
|
||||
$this->Session->setFlash('Taxonomy disabled.');
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
|
||||
public function update() {
|
||||
if (!$this->_isSiteAdmin()) throw new MethodNotAllowedException('You don\'t have permission to do that.');
|
||||
$result = $this->Taxonomy->update();
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$fails = 0;
|
||||
$successes = 0;
|
||||
if (!empty($result)) {
|
||||
if (isset($result['success'])) {
|
||||
foreach ($result['success'] as $id => &$success) {
|
||||
if (isset($success['old'])) $change = $success['namespace'] . ': updated from v' . $success['old'] . ' to v' . $success['new'];
|
||||
else $change = $success['namespace'] . ' v' . $success['new'] . ' installed';
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Taxonomy',
|
||||
'model_id' => $id,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'update',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Taxonomy updated',
|
||||
'change' => $change,
|
||||
));
|
||||
$successes++;
|
||||
}
|
||||
}
|
||||
if (isset($result['fails'])) {
|
||||
foreach ($result['fails'] as $id => &$fail) {
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Taxonomy',
|
||||
'model_id' => $id,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'update',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Taxonomy failed to update',
|
||||
'change' => $fail['namespace'] . ' could not be installed/updated. Error: ' . $fail['fail'],
|
||||
));
|
||||
$fails++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $this->Auth->user('Organisation')['name'],
|
||||
'model' => 'Taxonomy',
|
||||
'model_id' => 0,
|
||||
'email' => $this->Auth->user('email'),
|
||||
'action' => 'update',
|
||||
'user_id' => $this->Auth->user('id'),
|
||||
'title' => 'Taxonomy update (nothing to update)',
|
||||
'change' => 'Executed an update of the taxonomy library, but there was nothing to update.',
|
||||
));
|
||||
}
|
||||
if ($successes == 0 && $fails == 0) $this->Session->setFlash('All taxonomy libraries are up to date already.');
|
||||
else if ($successes == 0) $this->Session->setFlash('Could not update any of the taxonomy libraries');
|
||||
else {
|
||||
$message = 'Successfully updated ' . $successes . ' taxonomy libraries.';
|
||||
if ($fails != 0) $message . ' However, could not update ' . $fails . ' taxonomy libraries.';
|
||||
$this->Session->setFlash($message);
|
||||
}
|
||||
$this->redirect(array('controller' => 'taxonomies', 'action' => 'index'));
|
||||
/*debug($this->Taxonomy->getTaxonomy('1'));
|
||||
debug($this->Taxonomy->listTaxonomies());
|
||||
debug($this->Taxonomy->getTaxonomy('1', array('full' => true)));
|
||||
debug($this->Taxonomy->listTaxonomies(array('full' => true)));*/
|
||||
}
|
||||
}
|
|
@ -80,37 +80,71 @@ class AppModel extends Model {
|
|||
$sql = 'ALTER TABLE `logs` ADD `ip` varchar(45) COLLATE utf8_bin DEFAULT NULL;';
|
||||
break;
|
||||
case '24betaupdates':
|
||||
$sql = 'ALTER TABLE `shadow_attributes` ADD `proposal_to_delete` BOOLEAN NOT NULL';
|
||||
$sqlArray = array();
|
||||
$sqlArray[] = 'ALTER TABLE `shadow_attributes` ADD `proposal_to_delete` BOOLEAN NOT NULL';
|
||||
|
||||
$sqlArray[] = 'ALTER TABLE `logs` MODIFY `change` text COLLATE utf8_bin NOT NULL';
|
||||
|
||||
$sqlArray[] = "CREATE TABLE IF NOT EXISTS `taxonomies` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`namespace` varchar(255) COLLATE utf8_bin NOT NULL,
|
||||
`description` text COLLATE utf8_bin NOT NULL,
|
||||
`version` int(11) NOT NULL,
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ;";
|
||||
|
||||
$sqlArray[] = "CREATE TABLE IF NOT EXISTS `taxonomy_entries` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`taxonomy_predicate_id` int(11) NOT NULL,
|
||||
`value` text COLLATE utf8_bin NOT NULL,
|
||||
`expanded` text COLLATE utf8_bin NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `taxonomy_predicate_id` (`taxonomy_predicate_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;";
|
||||
|
||||
$sqlArray[] = "CREATE TABLE IF NOT EXISTS `taxonomy_predicates` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`taxonomy_id` int(11) NOT NULL,
|
||||
`value` text COLLATE utf8_bin NOT NULL,
|
||||
`expanded` text COLLATE utf8_bin NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `taxonomy_id` (`taxonomy_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;";
|
||||
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
try {
|
||||
$this->query($sql);
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => 'SYSTEM',
|
||||
'model' => 'Server',
|
||||
'model_id' => 0,
|
||||
'email' => 'SYSTEM',
|
||||
'action' => 'update_database',
|
||||
'user_id' => 0,
|
||||
'title' => 'Successfuly executed the SQL query for ' . $command,
|
||||
'change' => 'The executed SQL query was: ' . $sql
|
||||
));
|
||||
} catch (Exception $e) {
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => 'SYSTEM',
|
||||
'model' => 'Server',
|
||||
'model_id' => 0,
|
||||
'email' => 'SYSTEM',
|
||||
'action' => 'update_database',
|
||||
'user_id' => 0,
|
||||
'title' => 'Issues executing the SQL query for ' . $command,
|
||||
'change' => 'The executed SQL query was: ' . $sql . PHP_EOL . ' The returned error is: ' . $e->getMessage()
|
||||
));
|
||||
if (!isset($sqlArray)) $sqlArray = array($sql);
|
||||
foreach ($sqlArray as $sql) {
|
||||
try {
|
||||
$this->query($sql);
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => 'SYSTEM',
|
||||
'model' => 'Server',
|
||||
'model_id' => 0,
|
||||
'email' => 'SYSTEM',
|
||||
'action' => 'update_database',
|
||||
'user_id' => 0,
|
||||
'title' => 'Successfuly executed the SQL query for ' . $command,
|
||||
'change' => 'The executed SQL query was: ' . $sql
|
||||
));
|
||||
} catch (Exception $e) {
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => 'SYSTEM',
|
||||
'model' => 'Server',
|
||||
'model_id' => 0,
|
||||
'email' => 'SYSTEM',
|
||||
'action' => 'update_database',
|
||||
'user_id' => 0,
|
||||
'title' => 'Issues executing the SQL query for ' . $command,
|
||||
'change' => 'The executed SQL query was: ' . $sql . PHP_EOL . ' The returned error is: ' . $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
if ($clean) $this->cleanCacheFiles();
|
||||
return true;
|
||||
|
|
|
@ -38,7 +38,10 @@ class Log extends AppModel {
|
|||
'version_warning',
|
||||
'auth',
|
||||
'auth_fail',
|
||||
'reset_auth_key'
|
||||
'reset_auth_key',
|
||||
'update',
|
||||
'enable',
|
||||
'disable'
|
||||
)),
|
||||
'message' => 'Options : ...'
|
||||
)
|
||||
|
|
|
@ -144,4 +144,14 @@ class Tag extends AppModel {
|
|||
for ($i = 0; $i < 3; $i++) $colour .= str_pad(dechex(mt_rand(0,255)), 2, '0', STR_PAD_LEFT);
|
||||
return $colour;
|
||||
}
|
||||
|
||||
public function quickAdd($name) {
|
||||
$this->create();
|
||||
$data = array(
|
||||
'name' => $name,
|
||||
'colour' => $this->random_color(),
|
||||
'exportable' => 1
|
||||
);
|
||||
return ($this->save($data));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
class Taxonomy extends AppModel{
|
||||
public $useTable = 'taxonomies';
|
||||
public $recursive = -1;
|
||||
public $actsAs = array(
|
||||
'Containable',
|
||||
);
|
||||
|
||||
public $validate = array(
|
||||
'namespace' => array(
|
||||
'rule' => array('valueNotEmpty'),
|
||||
),
|
||||
'description' => array(
|
||||
'rule' => array('valueNotEmpty'),
|
||||
),
|
||||
'version' => array(
|
||||
'rule' => array('numeric'),
|
||||
)
|
||||
);
|
||||
|
||||
public $hasMany = array(
|
||||
'TaxonomyPredicate' => array(
|
||||
'dependent' => true
|
||||
)
|
||||
);
|
||||
|
||||
public function beforeValidate($options = array()) {
|
||||
parent::beforeValidate();
|
||||
return true;
|
||||
}
|
||||
|
||||
public function update() {
|
||||
$directories = glob(APP . 'files' . DS . 'taxonomies' . DS . '*', GLOB_ONLYDIR);
|
||||
foreach ($directories as $k => &$dir) {
|
||||
$dir = str_replace(APP . 'files' . DS . 'taxonomies' . DS, '', $dir);
|
||||
if ($dir === 'tools') unset($directories[$k]);
|
||||
}
|
||||
$updated = array();
|
||||
foreach ($directories as &$dir) {
|
||||
$file = new File (APP . 'files' . DS . 'taxonomies' . DS . $dir . DS . 'machinetag.json');
|
||||
$vocab = json_decode($file->read(), true);
|
||||
$file->close();
|
||||
$current = $this->find('first', array(
|
||||
'conditions' => array('namespace' => $vocab['namespace']),
|
||||
'recursive' => -1,
|
||||
'fields' => array('version', 'enabled')
|
||||
));
|
||||
if (empty($current) || $vocab['version'] > $current['Taxonomy']['version']) {
|
||||
$result = $this->__updateVocab($vocab, $current);
|
||||
debug($result);
|
||||
if (is_numeric($result)) {
|
||||
$updated['success'][$result] = array('namespace' => $vocab['namespace'], 'new' => $vocab['version']);
|
||||
if (!empty($current)) $updated['success'][$result]['old'] = $current['Taxonomy']['version'];
|
||||
} else {
|
||||
$updated['fails'][] = array('namespace' => $vocab['namespace'], 'fail' => json_encode($result));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $updated;
|
||||
}
|
||||
|
||||
private function __updateVocab(&$vocab, &$current) {
|
||||
$enabled = false;
|
||||
$taxonomy = array();
|
||||
if (!empty($current)) {
|
||||
if ($current['Taxonomy']['enabled']) $enabled = true;
|
||||
$this->delete($current['Taxonomy']['id']);
|
||||
}
|
||||
$taxonomy['Taxonomy'] = array('namespace' => $vocab['namespace'], 'description' => $vocab['description'], 'version' => $vocab['version'], 'enabled' => $enabled);
|
||||
$predicateLookup = array();
|
||||
foreach ($vocab['predicates'] as $k => &$predicate) {
|
||||
$taxonomy['Taxonomy']['TaxonomyPredicate'][$k] = $predicate;
|
||||
$predicateLookup[$predicate['value']] = $k;
|
||||
}
|
||||
if (!empty($vocab['values'])) foreach ($vocab['values'] as &$value) $taxonomy['Taxonomy']['TaxonomyPredicate'][$predicateLookup[$value['predicate']]]['TaxonomyEntry'] = $value['entry'];
|
||||
$result = $this->saveAssociated($taxonomy, array('deep' => true));
|
||||
if ($result) return $this->id;
|
||||
return $this->validationErrors;
|
||||
}
|
||||
|
||||
public function getTaxonomy($id, $options = array('full' => false)) {
|
||||
$this->Tag = ClassRegistry::init('Tag');
|
||||
$recursive = -1;
|
||||
if ($options['full']) $recursive = 2;
|
||||
$taxonomy = $this->find('first', array(
|
||||
'recursive' => $recursive,
|
||||
'conditions' => array('Taxonomy.id' => $id)
|
||||
));
|
||||
$tags_temp = $this->Tag->find('all', array(
|
||||
'recursive' => -1,
|
||||
'contain' => 'EventTag',
|
||||
'conditions' => array('name LIKE' => $taxonomy['Taxonomy']['namespace'] . '%'),
|
||||
));
|
||||
$tags = array();
|
||||
foreach ($tags_temp as &$temp) {
|
||||
$tags[$temp['Tag']['name']] = $temp;
|
||||
}
|
||||
unset($tags_temp);
|
||||
if (empty($taxonomy)) return false;
|
||||
$entries = array();
|
||||
foreach ($taxonomy['TaxonomyPredicate'] as &$predicate) {
|
||||
if (isset($predicate['TaxonomyEntry']) && !empty($predicate['TaxonomyEntry'])) {
|
||||
foreach ($predicate['TaxonomyEntry'] as &$entry) {
|
||||
$temp = array('tag' => $taxonomy['Taxonomy']['namespace'] . ':' . $predicate['value'] . '="' . $entry['value'] . '"');
|
||||
if (isset($predicate['expanded']) && isset($entry['expanded'])) $temp['expanded'] = $predicate['expanded'] . ': ' . $entry['expanded'];
|
||||
$temp['existing_tag'] = isset($tags[$temp['tag']]) ? $tags[$temp['tag']] : false;
|
||||
$entries[] = $temp;
|
||||
}
|
||||
} else {
|
||||
$temp = array('tag' => $taxonomy['Taxonomy']['namespace'] . ':' . $predicate['value']);
|
||||
$temp['existing_tag'] = isset($tags[$temp['tag']]) ? $tags[$temp['tag']] : false;
|
||||
if (isset($predicate['expanded'])) $temp['expanded'] = $predicate['expanded'];
|
||||
$entries[] = $temp;
|
||||
}
|
||||
}
|
||||
$taxonomy = array('Taxonomy' => $taxonomy['Taxonomy']);
|
||||
$taxonomy['entries'] = $entries;
|
||||
return $taxonomy;
|
||||
}
|
||||
|
||||
public function listTaxonomies($options = array('full' => false, 'enabled' => false)) {
|
||||
$recursive = -1;
|
||||
if ($options['full']) $recursive = 2;
|
||||
return $this->find('all', array(
|
||||
'recursive' => $recursive,
|
||||
));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
class TaxonomyEntry extends AppModel{
|
||||
public $useTable = 'taxonomy_entries';
|
||||
public $recursive = -1;
|
||||
public $actsAs = array(
|
||||
'Containable',
|
||||
);
|
||||
|
||||
public $validate = array(
|
||||
'value' => array(
|
||||
'rule' => array('valueNotEmpty'),
|
||||
),
|
||||
'expanded' => array(
|
||||
'rule' => array('valueNotEmpty'),
|
||||
),
|
||||
);
|
||||
|
||||
public $belongsTo = array(
|
||||
'TaxonomyPredicate'
|
||||
);
|
||||
|
||||
public function beforeValidate($options = array()) {
|
||||
parent::beforeValidate();
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
class TaxonomyPredicate extends AppModel{
|
||||
public $useTable = 'taxonomy_predicates';
|
||||
public $recursive = -1;
|
||||
public $actsAs = array(
|
||||
'Containable',
|
||||
);
|
||||
|
||||
public $validate = array(
|
||||
'value' => array(
|
||||
'rule' => array('valueNotEmpty'),
|
||||
),
|
||||
'expanded' => array(
|
||||
'rule' => array('valueNotEmpty'),
|
||||
),
|
||||
);
|
||||
|
||||
public $hasMany = array(
|
||||
'TaxonomyEntry' => array(
|
||||
'dependent' => true
|
||||
)
|
||||
);
|
||||
|
||||
public function beforeValidate($options = array()) {
|
||||
parent::beforeValidate();
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -22,7 +22,6 @@
|
|||
<?php if ($isAclAdd): ?>
|
||||
<li><a href="<?php echo $baseurl;?>/events/add">Add Event</a></li>
|
||||
<?php endif; ?>
|
||||
<li class="divider"></li>
|
||||
<li><a href="<?php echo $baseurl;?>/attributes/index">List Attributes</a></li>
|
||||
<li><a href="<?php echo $baseurl;?>/attributes/search">Search Attributes</a></li>
|
||||
<li class="divider"></li>
|
||||
|
@ -33,6 +32,7 @@
|
|||
<?php if ($isAclTagger): ?>
|
||||
<li><a href="<?php echo $baseurl;?>/tags/add">Add Tag</a></li>
|
||||
<?php endif; ?>
|
||||
<li><a href="<?php echo $baseurl;?>/taxonomies/index">List Taxonomies</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="<?php echo $baseurl;?>/templates/index">List Templates</a></li>
|
||||
<?php if ($isAclTemplate): ?>
|
||||
|
|
|
@ -243,6 +243,19 @@
|
|||
endif;
|
||||
break;
|
||||
|
||||
case 'taxonomies': ?>
|
||||
<li id='liindex'><a href="<?php echo $baseurl;?>/taxonomies/index">List Taxonomies</a></li>
|
||||
<?php if ($menuItem === 'view'): ?>
|
||||
<li id='liview'><a href="">View Taxonomy</a></li>
|
||||
<?php
|
||||
endif;
|
||||
if ($isSiteAdmin):
|
||||
?>
|
||||
<li id='liupdate'><?php echo $this->Form->postLink('Update Taxonomies', array('controller' => 'taxonomies', 'action' => 'update'));?></li>
|
||||
<?php
|
||||
endif;
|
||||
break;
|
||||
|
||||
case 'templates': ?>
|
||||
<li id='liindex'><a href="<?php echo $baseurl;?>/templates/index">List Templates</a></li>
|
||||
<?php if ($isSiteAdmin || $isAclTemplate): ?>
|
||||
|
|
|
@ -31,7 +31,6 @@ foreach ($list as $item): ?>
|
|||
<td class="short"><?php echo h($item['Tag']['id']); ?> </td>
|
||||
<td class="short"><span class="<?php echo ($item['Tag']['exportable'] ? 'icon-ok' : 'icon-remove'); ?>"></span></td>
|
||||
<td><a href="<?php echo $baseurl."/events/index/searchtag:".$item['Tag']['id']; ?>" class="tag" style="background-color: <?php echo h($item['Tag']['colour']); ?>;color:<?php echo $this->TextColour->getTextColour($item['Tag']['colour']); ?>"><?php echo h($item['Tag']['name']); ?></a></td>
|
||||
<td><a href="<?php echo $baseurl."/events/index/searchtag:".$item['Tag']['id']; ?>" class="tag" style="background-color: <?php echo h($item['Tag']['colour']); ?>;color:<?php echo $this->TextColour->getTextColour($item['Tag']['colour']); ?>"><?php echo h($item['Tag']['name']); ?></a></td>
|
||||
<td class="short"><?php echo h($item['Tag']['count']); ?> </td>
|
||||
<?php if ($isAclTagger): ?>
|
||||
<td class="short action-links">
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
<div class="taxonomies index">
|
||||
<h2>Taxonomies</h2>
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
<?php
|
||||
$this->Paginator->options(array(
|
||||
'update' => '.span12',
|
||||
'evalScripts' => true,
|
||||
'before' => '$(".progress").show()',
|
||||
'complete' => '$(".progress").hide()',
|
||||
));
|
||||
|
||||
echo $this->Paginator->prev('« ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
|
||||
echo $this->Paginator->next(__('next') . ' »', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
<table class="table table-striped table-hover table-condensed">
|
||||
<tr>
|
||||
<th><?php echo $this->Paginator->sort('id');?></th>
|
||||
<th><?php echo $this->Paginator->sort('namespace');?></th>
|
||||
<th><?php echo $this->Paginator->sort('description');?></th>
|
||||
<th><?php echo $this->Paginator->sort('version');?></th>
|
||||
<th><?php echo $this->Paginator->sort('enabled');?></th>
|
||||
<th class="actions"><?php echo __('Actions');?></th>
|
||||
</tr><?php
|
||||
foreach ($taxonomies as $item): ?>
|
||||
<tr>
|
||||
<td class="short" ondblclick="document.location.href ='<?php echo $baseurl."/taxonomies/view/".h($item['Taxonomy']['id']);?>'"><?php echo h($item['Taxonomy']['id']); ?> </td>
|
||||
<td class="short" ondblclick="document.location.href ='<?php echo $baseurl."/taxonomies/view/".h($item['Taxonomy']['id']);?>'"><?php echo h($item['Taxonomy']['namespace']); ?> </td>
|
||||
<td ondblclick="document.location.href ='<?php echo $baseurl."/taxonomies/view/".h($item['Taxonomy']['id']);?>'"><?php echo h($item['Taxonomy']['description']); ?> </td>
|
||||
<td class="short" ondblclick="document.location.href ='<?php echo $baseurl."/taxonomies/view/".h($item['Taxonomy']['id']);?>'"><?php echo h($item['Taxonomy']['version']); ?> </td>
|
||||
<td class="short" ondblclick="document.location.href ='<?php echo $baseurl."/taxonomies/view/".h($item['Taxonomy']['id']);?>'"><?php echo $item['Taxonomy']['enabled'] ? '<span class="green">Yes</span>' : '<span class="red">No</span>'; ?> </td>
|
||||
<td class="short action-links">
|
||||
<?php
|
||||
if ($isSiteAdmin) {
|
||||
if ($item['Taxonomy']['enabled']) {
|
||||
echo $this->Form->postLink('', array('action' => 'disable', h($item['Taxonomy']['id'])), array('class' => 'icon-minus', 'title' => 'Disable'), ('Are you sure you want to disable this taxonomy library?'));
|
||||
} else {
|
||||
echo $this->Form->postLink('', array('action' => 'enable', h($item['Taxonomy']['id'])), array('class' => 'icon-plus', 'title' => 'Enable'), ('Are you sure you want to enable this taxonomy library?'));
|
||||
}
|
||||
}
|
||||
?>
|
||||
<a href='<?php echo $baseurl."/taxonomies/view/". h($item['Taxonomy']['id']);?>' class = "icon-list-alt" title = "View"></a>
|
||||
</td>
|
||||
</tr><?php
|
||||
endforeach; ?>
|
||||
</table>
|
||||
<p>
|
||||
<?php
|
||||
echo $this->Paginator->counter(array(
|
||||
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
|
||||
));
|
||||
?>
|
||||
</p>
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
<?php
|
||||
echo $this->Paginator->prev('« ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
|
||||
echo $this->Paginator->next(__('next') . ' »', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->element('side_menu', array('menuList' => 'taxonomies', 'menuItem' => 'index'));
|
||||
?>
|
|
@ -0,0 +1,122 @@
|
|||
<div class="taxonomy view">
|
||||
<h2><?php echo h(strtoupper($taxonomy['namespace']));?> Taxonomy Library</h2>
|
||||
<dl>
|
||||
<dt>Id</dt>
|
||||
<dd>
|
||||
<?php echo h($taxonomy['id']); ?>
|
||||
|
||||
</dd>
|
||||
<dt>Namespace</dt>
|
||||
<dd>
|
||||
<?php echo h($taxonomy['namespace']); ?>
|
||||
|
||||
</dd>
|
||||
<dt>Description</dt>
|
||||
<dd>
|
||||
<?php echo h($taxonomy['description']); ?>
|
||||
|
||||
</dd>
|
||||
<dt>Version</dt>
|
||||
<dd>
|
||||
<?php echo h($taxonomy['version']); ?>
|
||||
|
||||
</dd>
|
||||
<dt>Enabled</dt>
|
||||
<dd>
|
||||
<?php echo $taxonomy['enabled'] ? '<span class="green">Yes</span> ' : '<span class="red">No</span> ';
|
||||
if ($isSiteAdmin) {
|
||||
if ($taxonomy['enabled']) {
|
||||
echo $this->Form->postLink('(disable)', array('action' => 'disable', h($taxonomy['id'])), array('title' => 'Disable'), ('Are you sure you want to disable this taxonomy library?'));
|
||||
} else {
|
||||
echo $this->Form->postLink('(enable)', array('action' => 'enable', h($taxonomy['id'])), array('title' => 'Enable'), ('Are you sure you want to enable this taxonomy library?'));
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
<?php
|
||||
$this->Paginator->options(array(
|
||||
'update' => '.span12',
|
||||
'evalScripts' => true,
|
||||
'before' => '$(".progress").show()',
|
||||
'complete' => '$(".progress").hide()',
|
||||
));
|
||||
|
||||
echo $this->Paginator->prev('« ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
|
||||
echo $this->Paginator->next(__('next') . ' »', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
<table class="table table-striped table-hover table-condensed">
|
||||
<tr>
|
||||
<th><?php echo $this->Paginator->sort('tag');?></th>
|
||||
<th><?php echo $this->Paginator->sort('expanded');?></th>
|
||||
<th><?php echo $this->Paginator->sort('events');?></th>
|
||||
<th><?php echo $this->Paginator->sort('tag');?></th>
|
||||
</tr><?php
|
||||
foreach ($entries as $k => $item): ?>
|
||||
<tr>
|
||||
<td class="short"><?php echo h($item['tag']); ?> </td>
|
||||
<td><?php echo h($item['expanded']); ?> </td>
|
||||
<td class="short">
|
||||
<?php
|
||||
if ($item['existing_tag']) {
|
||||
?>
|
||||
<a href='<?php echo $baseurl."/events/index/searchtag:". h($item['existing_tag']['Tag']['id']);?>'><?php echo count($item['existing_tag']['EventTag']);?></a>
|
||||
<?php
|
||||
} else {
|
||||
echo 'N/A';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td class="short">
|
||||
<?php
|
||||
if ($item['existing_tag']):
|
||||
$url = $baseurl . '/events/index/searchtag:' . h($item['existing_tag']['Tag']['id']);
|
||||
if ($isAclTagger) $url = $baseurl . '/tags/edit/' . h($item['existing_tag']['Tag']['id']);
|
||||
?>
|
||||
<a href="<?php echo $url;?>" class="<?php echo $isAclTagger ? 'tagFirstHalf' : 'tag' ?>" style="background-color:<?php echo h($item['existing_tag']['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($item['existing_tag']['Tag']['colour']);?>"><?php echo h($item['existing_tag']['Tag']['name']); ?></a>
|
||||
<?php
|
||||
else:
|
||||
if ($isAclTagger && $taxonomy['enabled']) {
|
||||
echo $this->Form->create('Tag', array('id' => 'quick_' . h($k), 'url' => '/tags/quickAdd/', 'style' => 'margin:0px;'));
|
||||
echo $this->Form->input('name', array('type' => 'hidden', 'value' => $item['tag']));
|
||||
?>
|
||||
<span class="icon-plus useCursorPointer" onClick="submitQuickTag('<?php echo 'quick_' . h($k); ?>');"></span>
|
||||
<?php
|
||||
echo $this->Form->end();
|
||||
} else {
|
||||
echo 'N/A';
|
||||
}
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<p>
|
||||
<?php
|
||||
echo $this->Paginator->counter(array(
|
||||
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
|
||||
));
|
||||
?>
|
||||
</p>
|
||||
<div class="pagination">
|
||||
<ul>
|
||||
<?php
|
||||
echo $this->Paginator->prev('« ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
echo $this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span'));
|
||||
echo $this->Paginator->next(__('next') . ' »', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'));
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
echo $this->element('side_menu', array('menuList' => 'taxonomies', 'menuItem' => 'view'));
|
||||
?>
|
||||
|
|
@ -0,0 +1 @@
|
|||
Subproject commit a7e2b4104597b52f110580b8204dcf820fa9f5d2
|
|
@ -191,6 +191,10 @@ function activateField(type, id, field, event) {
|
|||
});
|
||||
}
|
||||
|
||||
function submitQuickTag(form) {
|
||||
$('#' + form).submit();
|
||||
}
|
||||
|
||||
//if someone clicks an inactive field, replace it with the hidden form field. Also, focus it and bind a focusout event, so that it gets saved if the user clicks away.
|
||||
//If a user presses enter, submit the form
|
||||
function postActivationScripts(name, type, id, field, event) {
|
||||
|
|
Loading…
Reference in New Issue