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 disabled
pull/762/head
iglocska 2015-11-24 03:27:14 +01:00
parent c5ef4e1d2d
commit 3784209cf5
19 changed files with 706 additions and 30 deletions

1
.gitignore vendored
View File

@ -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

3
.gitmodules vendored
View File

@ -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

View File

@ -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
--

View File

@ -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;
-- --------------------------------------------------------

View File

@ -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.');

View File

@ -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)));*/
}
}

View File

@ -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;

View File

@ -38,7 +38,10 @@ class Log extends AppModel {
'version_warning',
'auth',
'auth_fail',
'reset_auth_key'
'reset_auth_key',
'update',
'enable',
'disable'
)),
'message' => 'Options : ...'
)

View File

@ -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));
}
}

129
app/Model/Taxonomy.php Normal file
View File

@ -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,
));
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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): ?>

View File

@ -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): ?>

View File

@ -31,7 +31,6 @@ foreach ($list as $item): ?>
<td class="short"><?php echo h($item['Tag']['id']); ?>&nbsp;</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']); ?>&nbsp;</td>
<?php if ($isAclTagger): ?>
<td class="short action-links">

View File

@ -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('&laquo; ' . __('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') . ' &raquo;', 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']); ?>&nbsp;</td>
<td class="short" ondblclick="document.location.href ='<?php echo $baseurl."/taxonomies/view/".h($item['Taxonomy']['id']);?>'"><?php echo h($item['Taxonomy']['namespace']); ?>&nbsp;</td>
<td ondblclick="document.location.href ='<?php echo $baseurl."/taxonomies/view/".h($item['Taxonomy']['id']);?>'"><?php echo h($item['Taxonomy']['description']); ?>&nbsp;</td>
<td class="short" ondblclick="document.location.href ='<?php echo $baseurl."/taxonomies/view/".h($item['Taxonomy']['id']);?>'"><?php echo h($item['Taxonomy']['version']); ?>&nbsp;</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>'; ?>&nbsp;</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('&laquo; ' . __('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') . ' &raquo;', 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'));
?>

View File

@ -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']); ?>
&nbsp;
</dd>
<dt>Namespace</dt>
<dd>
<?php echo h($taxonomy['namespace']); ?>
&nbsp;
</dd>
<dt>Description</dt>
<dd>
<?php echo h($taxonomy['description']); ?>
&nbsp;
</dd>
<dt>Version</dt>
<dd>
<?php echo h($taxonomy['version']); ?>
&nbsp;
</dd>
<dt>Enabled</dt>
<dd>
<?php echo $taxonomy['enabled'] ? '<span class="green">Yes</span>&nbsp;&nbsp;' : '<span class="red">No</span>&nbsp;&nbsp;';
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?'));
}
}
?>
&nbsp;
</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('&laquo; ' . __('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') . ' &raquo;', 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']); ?>&nbsp;</td>
<td><?php echo h($item['expanded']); ?>&nbsp;</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('&laquo; ' . __('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') . ' &raquo;', 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'));
?>

1
app/files/taxonomies Submodule

@ -0,0 +1 @@
Subproject commit a7e2b4104597b52f110580b8204dcf820fa9f5d2

View File

@ -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) {