Merge branch 'master' into plugin_support

This commit is contained in:
Emmanuel Papin 2014-11-21 14:02:12 +01:00
commit dde1e13f22
19 changed files with 597 additions and 51 deletions

View File

@ -105,29 +105,39 @@ root@host:~# gdebi /root/zoneminder_1.26.4-1_amd64.deb;
Additional repositories must be added before one can build zoneminder on CentOS or RHEL:
1. RepoForge (formerly RPMForge) http://repoforge.org/use/
1. Zmrepo [ZoneMinder WiKi](http://www.zoneminder.com/wiki/index.php/CentOS#Zmrepo_-_A_ZoneMinder_repository_for_RPM_based_distros)
2. EPEL https://fedoraproject.org/wiki/EPEL
3. Optional RPMFusion: http://rpmfusion.org/ [SEE NOTE]
3. RPMFusion: http://rpmfusion.org/
[NOTE]<br>
The RPMFusion repo contains significantly newer versions of ffmpeg and vlc. This leads to significantly better camera support. However, the RPMFusion repo contains packages that conflict with the other two repos. In order to resolve this, one must also install the yum priorities pacakge and use that to prioritize your repos in the following order:
When adding third party repositories, it is highly recommended that the user also install and configure yum priorities as documented in the [CentOS WiKi](http://wiki.centos.org/PackageManagement/Yum/Priorities)
Prioritize the repositories:
1. Base
2. RPMFusion
3. EPEL
4. RPMForge
For instructions on yum priorities, visit this page:
http://wiki.centos.org/PackageManagement/Yum/Priorities
2. EPEL
3. RPMFusion
4. Zmrepo
Once your repos are in order, install the following:
```bash
sudo yum install automake bzip2-devel ffmpeg ffmpeg-devel gnutls-devel httpd libjpeg-turbo libjpeg-turbo-devel mysql-devel mysql-server pcre-devel \
sudo yum install cmake bzip2-devel ffmpeg ffmpeg-devel gnutls-devel httpd libjpeg-turbo libjpeg-turbo-devel mysql-devel mysql-server pcre-devel \
perl-Archive-Tar perl-Archive-Zip perl-Convert-BinHex perl-Date-Manip perl-DBD-MySQL perl-DBI perl-Device-SerialPort perl-Email-Date-Format perl-IO-stringy \
perl-IO-Zlib perl-MailTools perl-MIME-Lite perl-MIME-tools perl-MIME-Types perl-Module-Load perl-Package-Constants perl-Sys-Mmap perl-Time-HiRes \
perl-TimeDate perl-YAML-Syck php php-cli php-mysql x264 vlc-devel vlc-core libcurl libcurl-devel
perl-TimeDate perl-YAML-Syck perl-X10 perl-URI-Encode php php-cli php-mysql x264 vlc-devel vlc-core \
libcurl libcurl-devel polkit-devel git
```
To build from the master branch:
```bash
git clone https://github.com/ZoneMinder/ZoneMinder.git
cd ZoneMinder
cmake .
make
sudo make install
```
IMPORTANT: Don't forget the trailing "." when calling cmake
#### Docker
Docker is a system to run applications inside isolated containers. ZoneMinder, and the ZM webserver, will run using the
@ -159,4 +169,14 @@ the following steps.
6. Create new Pull Request
7. The team will then review, discuss and hopefully merge your changes.
### Package Maintainters
Many of the ZoneMinder configration variable default values are not configurable at build time through autotools or cmake. A new tool called *zmeditconfigdata.sh* has been added to allow package maintainers to manipulate any variable stored in ConfigData.pm without patching the source.
For example, let's say I have created a new ZoneMinder package that contains the cambolzola javascript file. However, by default cambozola support is turned off. To fix that, add this to the pacakging script:
```bash
./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes
```
Note that zmeditconfigdata.sh is intended to be called, from the root build folder, prior to running cmake or configure.
[![Analytics](https://ga-beacon.appspot.com/UA-15147273-6/ZoneMinder/README.md)](https://github.com/igrigorik/ga-beacon)

View File

@ -7,7 +7,7 @@ Standards-Version: 3.9.2
Package: zoneminder
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, apache2 | httpd, libapache2-mod-php5 | libapache2-mod-fcgid | php5-fpm, php5, php5-mysql|php5-mysqlnd, libphp-serialization-perl, libdate-manip-perl, libmime-lite-perl, libmime-tools-perl, mariadb-client|mysql-client, libwww-perl, libarchive-tar-perl, libarchive-zip-perl, libdevice-serialport-perl, libpcre3, ffmpeg | libav-tools, rsyslog | system-log-daemon, libmodule-load-perl, libsys-mmap-perl, libjson-any-perl, netpbm, libavdevice53, libjpeg8, zip, libnet-sftp-foreign-perl, libio-pty-perl, libexpect-perl, libvlccore5 | libvlccore7, libvlc5, libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev, libpolkit-gobject-1-0
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, apache2, libapache2-mod-php5 | libapache2-mod-fcgid, php5, php5-mysql|php5-mysqlnd, libphp-serialization-perl, libdate-manip-perl, libmime-lite-perl, libmime-tools-perl, mariadb-client|mysql-client, libwww-perl, libarchive-tar-perl, libarchive-zip-perl, libdevice-serialport-perl, libpcre3, ffmpeg | libav-tools, rsyslog | system-log-daemon, libmodule-load-perl, libsys-mmap-perl, libjson-any-perl, netpbm, libavdevice53 | libavdevice55, libjpeg8, zip, libnet-sftp-foreign-perl, libio-pty-perl, libexpect-perl, libvlccore5 | libvlccore7 | libvlccore8, libvlc5, libcurl4-gnutls-dev | libcurl4-nss-dev | libcurl4-openssl-dev, libpolkit-gobject-1-0, liburi-encode-perl
Recommends: mysql-server|mariadb-server
Description: A video camera security and surveillance solution
ZoneMinder is intended for use in single or multi-camera video security

View File

@ -22,8 +22,6 @@ URL: http://www.zoneminder.com/
#Source: https://github.com/ZoneMinder/ZoneMinder/archive/v%{version}.tar.gz
Source: ZoneMinder-%{version}.tar.gz
Patch1: zoneminder-1.28.0-defaults.patch
BuildRequires: cmake gnutls-devel systemd-units bzip2-devel
BuildRequires: community-mysql-devel pcre-devel libjpeg-turbo-devel
BuildRequires: perl(Archive::Tar) perl(Archive::Zip)
@ -66,7 +64,13 @@ too much degradation of performance.
%prep
%setup -q -n ZoneMinder-%{version}
%patch1 -p0 -b .defaults
# Change the following default values
./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin/zm/nph-zms
./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes
./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm
./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR /var/spool/zoneminder-upload
./utils/zmeditconfigdata.sh ZM_OPT_CONTROL yes
%build
%cmake \

View File

@ -17,8 +17,6 @@ URL: http://www.zoneminder.com/
#Source0: https://github.com/ZoneMinder/ZoneMinder/archive/v%{version}.tar.gz
Source0: ZoneMinder-%{version}.tar.gz
Patch1: zoneminder-1.28.0-defaults.patch
BuildRequires: cmake gnutls-devel bzip2-devel
BuildRequires: mysql-devel pcre-devel libjpeg-turbo-devel
BuildRequires: perl(Archive::Tar) perl(Archive::Zip)
@ -63,7 +61,12 @@ too much degradation of performance.
%prep
%setup -q -n ZoneMinder-%{version}
%patch1 -p0 -b .defaults
# Change the following default values
./utils/zmeditconfigdata.sh ZM_PATH_ZMS /cgi-bin/zm/nph-zms
./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes
./utils/zmeditconfigdata.sh ZM_PATH_SWAP /dev/shm
./utils/zmeditconfigdata.sh ZM_UPLOAD_FTP_LOC_DIR /var/spool/zoneminder-upload
./utils/zmeditconfigdata.sh ZM_OPT_CONTROL yes
%build
# Have to override CMAKE_INSTALL_LIBDIR for cmake < 2.8.7 due to this bug:

View File

@ -33,8 +33,6 @@ require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our $VERSION = $ZoneMinder::Base::VERSION;
# ==========================================================================
#
# Axis V2 Control Protocol
@ -79,7 +77,7 @@ sub open
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION );
$self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
$self->{state} = 'open';
}

View File

@ -89,6 +89,8 @@ Parameters are :-
-u<dbuser>, --user=<dbuser> - Alternate DB user with privileges to alter DB
-p<dbpass>, --pass=<dbpass> - Password of alternate DB user with privileges to alter DB
-d<dir>,--dir=<dir> - Directory containing update files if not in default build location
-interactive - interact with the user
-nointeractive - do not interact with the user
");
exit( -1 );
}
@ -319,6 +321,8 @@ if ( $freshen )
saveConfigToDB();
}
# Don't do innoDB upgrade if not interactive
if ( $interactive ) {
# Now check for MyISAM Tables
my @MyISAM_Tables;
my $sql = "SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='zm' AND engine = 'MyISAM'";
@ -336,17 +340,18 @@ if ( @MyISAM_Tables ) {
my $response = <STDIN>;
chomp( $response );
if ( $response =~ /^[yY]$/ ) {
$dbh->do(q|SET sql_mode='traditional'|); # Elevate warnings to errors
print "\nConverting MyISAM tables to InnoDB. Please wait.\n";
foreach (@MyISAM_Tables) {
$dbh->do(q|SET sql_mode='traditional'|); # Elevate warnings to errors
my $sql = "ALTER TABLE $_ ENGINE = InnoDB";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
}
$dbh->do(q|SET sql_mode=''|); # Set mode back to default
}
}
}
} # end if interactive
if ( $version )
{

View File

@ -463,12 +463,12 @@ Monitor::Monitor(
{
if ( purpose != QUERY )
{
Error( "Shared data not initialised by capture daemon" );
Error( "Shared data not initialised by capture daemon for monitor %s", name );
exit( -1 );
}
else
{
Warning( "Shared data not initialised by capture daemon, some query functions may not be available or produce invalid results" );
Warning( "Shared data not initialised by capture daemon, some query functions may not be available or produce invalid results for monitor %s", name );
}
}

View File

@ -768,11 +768,10 @@ int RtspThread::run()
if ( !recvResponse( response ) )
return( -1 );
#endif
// Send a teardown message but don't expect a response as this may not be implemented on the server when using TCP
message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n";
if ( !sendCommand( message ) )
return( -1 );
if ( !recvResponse( response ) )
return( -1 );
delete mSources[ssrc];
mSources.clear();

100
utils/zmeditconfigdata.sh Executable file
View File

@ -0,0 +1,100 @@
#!/bin/bash
# This script allows the package maintainer to change the default value
# of any variable specified in ConfigData.pm without writing a patch.
# Run this script from your build folder, before running configure or cmake.
usage()
{
cat <<EOF
USAGE:
$0 VARIABLE DEFAULT [CONFIGDATA DIRECTORY]
Replace the default value, DEFAULT, of the specified ZoneMinder
variable, VARIABLE, located in ConfigData.pm.in.
Default folder for ConfigData is ./scripts/ZoneMinder/lib/ZoneMinder
Specify CONFIGDATA DIRETORY to override.
Run this script from your build folder, before running configure or cmake.
EXAMPLE:
zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes
WARNING:
The user supplied value for DEFAULT is not checked for sanity. For example,
changing ZM_LANG_DEFAULT to "pony" will cause bad things to happen!
EOF
}
if [ -z "$1" ] || [ -z "$2" ]; then
usage
exit 0
fi
# Check to see if this script has access to all the commands it needs
for CMD in set echo printf grep sed ; do
type $CMD &> /dev/null
if [ $? -ne 0 ]; then
echo
echo "ERROR: The script cannot find the required command \"${CMD}\"."
echo
exit 1
fi
done
escape()
{
escaped=""
local temp="$(printf %q "$1")"
escaped="$(echo $temp | sed 's/\//\\\//g')"
}
# Assign variables once they are properly escaped
escape $1
variable=$escaped
escape $2
default=$escaped
# Set the path to ConfigData
if [ -n "$3" ]; then
configdata="$3/ConfigData.pm.in"
else
configdata="./scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in"
fi
# Check to make sure we can find ConfigData
if [ ! -e "$configdata" ]; then
echo "CONFIGDATA FILE NOT FOUND: $configdata"
exit 1
fi
# Now that we've found ConfidData, verify the supplied variable
# is defined inside the ConfigData file.
if [ -z "$(grep $variable $configdata)" ]; then
echo "ZONEMINDER VARIABLE NOT FOUND: $variable"
exit 1
fi
# Update the supplied variable with the new default value.
# Don't stare too closely. You will burn your eyes out.
sed -i '/.*'${variable}'.*/{
$!{ N
s/\(.*'${variable}'.*\n.*\)\"\(.*\)\"/\1\"'${default}'\"/
t yes
P
D
:yes
}
}' $configdata
if [ "$?" != "0" ]; then
echo "SED RETURNED FAILURE"
exit 1
fi

View File

@ -0,0 +1,80 @@
<?php
App::uses('Component', 'Controller');
class ConfigParserComponent extends Component {
public function parseHints($hint) {
$string = "";
$hints = explode('|', $hint);
foreach ($hints as $hint) {
$string .= "<option value=\"$hint\">$hint</option>";
}
return $string;
}
public function getLabel($name) {
$width = 'col-md-4';
$string = '<div class="form-group">';
$string .= '<label for="%s" class="control-label %s">%s</label>';
$label = sprintf($string, $name, $width, $name);
$label .= '<div class="col-md-6">';
return $label;
}
public function getInput($name, $type, $id) {
if ($type == 'checkbox') {
$string = '<input id="%s" type="checkbox" ng-change="updateConfig(\'%s\', \'%s\')" ng-model="myModel.configData[\'%s\']" ng-true-value="1" ng-false-value="0"><span class="form-control-feedback"></span></div>';
} elseif ($type == 'text') {
$string = '<input id="%s" type="text" ng-change="updateConfig(\'%s\', \'%s\')" ng-model="myModel.configData[\'%s\']" class="form-control"><span class="form-control-feedback"></span></div>';
} elseif ($type == 'textarea') {
$string = '<textarea id="%s" ng-change="updateConfig(\'%s\', \'%s\')" class="form-control" rows="3" ng-model="myModel.configData[\'%s\']"></textarea><span class="form-control-feedback"></span></div>';
} elseif ($type == 'select') {
$string = '<select id="%s" ng-change="updateConfig(\'%s\', \'%s\')" class="form-control" ng-model="myModel.configData[\'%s\']">';
}
$input = sprintf($string, $name, $id, $name, $name);
return $input;
}
public function parseOptions($configs) {
$category = $configs[0]['Config']['Category'];
$string = "";
foreach ($configs as $option) {
$type = $option['Config']['Type'];
$name = $option['Config']['Name'];
$value = $option['Config']['Value'];
$hint = $option['Config']['Hint'];
$id = $option['Config']['Id'];
$string .= $this->getLabel($name);
switch ($type) {
case "boolean":
$string .= $this->getInput($name, 'checkbox', $id);
break;
case "text":
$string .= $this->getInput($name, 'textarea', $id);
break;
case "string":
if (strpos($hint, '|') === FALSE) {
$string .= $this->getInput($name, 'text', $id);
} else {
$string .= $this->getInput($name, 'select', $id);
$string .= $this->parseHints($hint);
$string .= '</select> <span class="form-control-feedback"></span> </div>';
}
break;
default:
$string .= $this->getInput($name, 'text', $id);
}
$string .= "</div><!-- End .form-group -->\n";
}
return $string;
}
}
?>

View File

@ -88,4 +88,50 @@ class ConfigsController extends AppController {
} else {
return $this->flash(__('The config could not be deleted. Please, try again.'), array('action' => 'index'));
}
}}
}
/**
* categories method
*
* Either return a list of distinct categories
* Or all configs under a certain category
*/
public function categories($category = null) {
if ($category != null) {
if (!$this->Config->find('first', array( 'conditions' => array('Config.Category' => $category)))) {
throw new NotFoundException(__('Invalid Config Category'));
}
$config = $this->Config->find('all', array(
'conditions' => array('Config.Category' => $category),
'recursive' => 0
));
$this->set(array(
'config' => $config,
'_serialize' => array('config')
));
} else {
$categories = $this->Config->find('all', array(
'fields' => array('DISTINCT Config.Category'),
'conditions' => array('Config.Category !=' => 'hidden'),
'recursive' => 0
));
$this->set(array(
'categories' => $categories,
'_serialize' => array('categories')
));
}
}
public function keyValue() {
$keyValues = $this->Config->find('list', array(
'fields' => array('Config.Name', 'Config.Value')
));
$this->set(array(
'keyValues' => $keyValues,
'_serialize' => array('keyValues')
));
}
}

View File

@ -0,0 +1,96 @@
<?php
App::uses('AppController', 'Controller');
/**
* Logs Controller
*
* @property Log $Log
* @property PaginatorComponent $Paginator
*/
class LogsController extends AppController {
/**
* Components
*
* @var array
*/
public $components = array('Paginator');
/**
* index method
*
* @return void
*/
public function index() {
$this->Log->recursive = 0;
$this->set('logs', $this->Paginator->paginate());
}
/**
* view method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function view($id = null) {
if (!$this->Log->exists($id)) {
throw new NotFoundException(__('Invalid log'));
}
$options = array('conditions' => array('Log.' . $this->Log->primaryKey => $id));
$this->set('log', $this->Log->find('first', $options));
}
/**
* add method
*
* @return void
*/
public function add() {
if ($this->request->is('post')) {
$this->Log->create();
if ($this->Log->save($this->request->data)) {
return $this->flash(__('The log has been saved.'), array('action' => 'index'));
}
}
}
/**
* edit method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function edit($id = null) {
if (!$this->Log->exists($id)) {
throw new NotFoundException(__('Invalid log'));
}
if ($this->request->is(array('post', 'put'))) {
if ($this->Log->save($this->request->data)) {
return $this->flash(__('The log has been saved.'), array('action' => 'index'));
}
} else {
$options = array('conditions' => array('Log.' . $this->Log->primaryKey => $id));
$this->request->data = $this->Log->find('first', $options);
}
}
/**
* delete method
*
* @throws NotFoundException
* @param string $id
* @return void
*/
public function delete($id = null) {
$this->Log->id = $id;
if (!$this->Log->exists()) {
throw new NotFoundException(__('Invalid log'));
}
$this->request->allowMethod('post', 'delete');
if ($this->Log->delete()) {
return $this->flash(__('The log has been deleted.'), array('action' => 'index'));
} else {
return $this->flash(__('The log could not be deleted. Please, try again.'), array('action' => 'index'));
}
}}

View File

@ -108,4 +108,21 @@ class MonitorsController extends AppController {
} else {
return $this->flash(__('The monitor could not be deleted. Please, try again.'), array('action' => 'index'));
}
}}
}
public function sourceTypes() {
$sourceTypes = $this->Monitor->query("describe Monitors Type;");
preg_match('/^enum\((.*)\)$/', $sourceTypes[0]['COLUMNS']['Type'], $matches);
foreach( explode(',', $matches[1]) as $value ) {
$enum[] = trim( $value, "'" );
}
$this->set(array(
'sourceTypes' => $enum,
'_serialize' => array('sourceTypes')
));
}
}

23
web/api/app/Model/Log.php Normal file
View File

@ -0,0 +1,23 @@
<?php
App::uses('AppModel', 'Model');
/**
* Log Model
*
*/
class Log extends AppModel {
/**
* Use table
*
* @var mixed False or table name
*/
public $useTable = 'Logs';
/**
* Primary key field
*
* @var string
*/
public $primaryKey = 'TimeKey';
}

View File

@ -0,0 +1 @@
echo json_encode($config);

View File

@ -0,0 +1,23 @@
<div class="logs form">
<?php echo $this->Form->create('Log'); ?>
<fieldset>
<legend><?php echo __('Add Log'); ?></legend>
<?php
echo $this->Form->input('Component');
echo $this->Form->input('Pid');
echo $this->Form->input('Level');
echo $this->Form->input('Code');
echo $this->Form->input('Message');
echo $this->Form->input('File');
echo $this->Form->input('Line');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
<div class="actions">
<h3><?php echo __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('List Logs'), array('action' => 'index')); ?></li>
</ul>
</div>

View File

@ -0,0 +1,25 @@
<div class="logs form">
<?php echo $this->Form->create('Log'); ?>
<fieldset>
<legend><?php echo __('Edit Log'); ?></legend>
<?php
echo $this->Form->input('TimeKey');
echo $this->Form->input('Component');
echo $this->Form->input('Pid');
echo $this->Form->input('Level');
echo $this->Form->input('Code');
echo $this->Form->input('Message');
echo $this->Form->input('File');
echo $this->Form->input('Line');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
<div class="actions">
<h3><?php echo __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Form->postLink(__('Delete'), array('action' => 'delete', $this->Form->value('Log.TimeKey')), null, __('Are you sure you want to delete # %s?', $this->Form->value('Log.TimeKey'))); ?></li>
<li><?php echo $this->Html->link(__('List Logs'), array('action' => 'index')); ?></li>
</ul>
</div>

View File

@ -0,0 +1,52 @@
<div class="logs index">
<h2><?php echo __('Logs'); ?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('TimeKey'); ?></th>
<th><?php echo $this->Paginator->sort('Component'); ?></th>
<th><?php echo $this->Paginator->sort('Pid'); ?></th>
<th><?php echo $this->Paginator->sort('Level'); ?></th>
<th><?php echo $this->Paginator->sort('Code'); ?></th>
<th><?php echo $this->Paginator->sort('Message'); ?></th>
<th><?php echo $this->Paginator->sort('File'); ?></th>
<th><?php echo $this->Paginator->sort('Line'); ?></th>
<th class="actions"><?php echo __('Actions'); ?></th>
</tr>
<?php foreach ($logs as $log): ?>
<tr>
<td><?php echo h($log['Log']['TimeKey']); ?>&nbsp;</td>
<td><?php echo h($log['Log']['Component']); ?>&nbsp;</td>
<td><?php echo h($log['Log']['Pid']); ?>&nbsp;</td>
<td><?php echo h($log['Log']['Level']); ?>&nbsp;</td>
<td><?php echo h($log['Log']['Code']); ?>&nbsp;</td>
<td><?php echo h($log['Log']['Message']); ?>&nbsp;</td>
<td><?php echo h($log['Log']['File']); ?>&nbsp;</td>
<td><?php echo h($log['Log']['Line']); ?>&nbsp;</td>
<td class="actions">
<?php echo $this->Html->link(__('View'), array('action' => 'view', $log['Log']['TimeKey'])); ?>
<?php echo $this->Html->link(__('Edit'), array('action' => 'edit', $log['Log']['TimeKey'])); ?>
<?php echo $this->Form->postLink(__('Delete'), array('action' => 'delete', $log['Log']['TimeKey']), array(), __('Are you sure you want to delete # %s?', $log['Log']['TimeKey'])); ?>
</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="paging">
<?php
echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));
echo $this->Paginator->numbers(array('separator' => ''));
echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled'));
?>
</div>
</div>
<div class="actions">
<h3><?php echo __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('New Log'), array('action' => 'add')); ?></li>
</ul>
</div>

View File

@ -0,0 +1,54 @@
<div class="logs view">
<h2><?php echo __('Log'); ?></h2>
<dl>
<dt><?php echo __('TimeKey'); ?></dt>
<dd>
<?php echo h($log['Log']['TimeKey']); ?>
&nbsp;
</dd>
<dt><?php echo __('Component'); ?></dt>
<dd>
<?php echo h($log['Log']['Component']); ?>
&nbsp;
</dd>
<dt><?php echo __('Pid'); ?></dt>
<dd>
<?php echo h($log['Log']['Pid']); ?>
&nbsp;
</dd>
<dt><?php echo __('Level'); ?></dt>
<dd>
<?php echo h($log['Log']['Level']); ?>
&nbsp;
</dd>
<dt><?php echo __('Code'); ?></dt>
<dd>
<?php echo h($log['Log']['Code']); ?>
&nbsp;
</dd>
<dt><?php echo __('Message'); ?></dt>
<dd>
<?php echo h($log['Log']['Message']); ?>
&nbsp;
</dd>
<dt><?php echo __('File'); ?></dt>
<dd>
<?php echo h($log['Log']['File']); ?>
&nbsp;
</dd>
<dt><?php echo __('Line'); ?></dt>
<dd>
<?php echo h($log['Log']['Line']); ?>
&nbsp;
</dd>
</dl>
</div>
<div class="actions">
<h3><?php echo __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('Edit Log'), array('action' => 'edit', $log['Log']['TimeKey'])); ?> </li>
<li><?php echo $this->Form->postLink(__('Delete Log'), array('action' => 'delete', $log['Log']['TimeKey']), null, __('Are you sure you want to delete # %s?', $log['Log']['TimeKey'])); ?> </li>
<li><?php echo $this->Html->link(__('List Logs'), array('action' => 'index')); ?> </li>
<li><?php echo $this->Html->link(__('New Log'), array('action' => 'add')); ?> </li>
</ul>
</div>