Merge branch 'master' of github.com:easysoft/zentaopms

Conflicts:
	module/dev/lang/en.php
This commit is contained in:
xia0ta0
2015-03-05 09:20:44 +08:00
56 changed files with 1320 additions and 95 deletions

View File

@@ -139,6 +139,8 @@ define('TABLE_ACTION', '`' . $config->db->prefix . 'action`');
define('TABLE_FILE', '`' . $config->db->prefix . 'file`');
define('TABLE_HISTORY', '`' . $config->db->prefix . 'history`');
define('TABLE_EXTENSION', '`' . $config->db->prefix . 'extension`');
define('TABLE_CRON', '`' . $config->db->prefix . 'cron`');
define('TABLE_MAILQUEUE', '`' . $config->db->prefix . 'mailqueue`');
if(!defined('TABLE_LANG')) define('TABLE_LANG', '`' . $config->db->prefix . 'lang`');
$config->objectTables['product'] = TABLE_PRODUCT;

44
db/update7.0.sql Normal file
View File

@@ -0,0 +1,44 @@
REPLACE INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'common', 'global', 'cron', '0');
DROP TABLE IF EXISTS `zt_cron`;
CREATE TABLE `zt_cron` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`m` varchar(20) NOT NULL,
`h` varchar(20) NOT NULL,
`dom` varchar(20) NOT NULL,
`mon` varchar(20) NOT NULL,
`dow` varchar(20) NOT NULL,
`command` text NOT NULL,
`remark` varchar(255) NOT NULL,
`type` varchar(20) NOT NULL,
`buildin` tinyint(1) NOT NULL DEFAULT '0',
`status` varchar(20) NOT NULL,
`lastTime` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
TRUNCATE `zt_cron`;
INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES
('*', '*', '*', '*', '*', '', '监控定时任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
('30', '23', '*', '*', '*', 'moduleName=project&methodName=computeburn', '更新燃尽图', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
('0', '1', '*', '*', '*', 'moduleName=report&methodName=remind', '每日任务提醒', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
('*/5', '*', '*', '*', '*', 'moduleName=svn&methodName=run', '同步SVN', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
('*/5', '*', '*', '*', '*', 'moduleName=git&methodName=run', '同步GIT', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
('30', '0', '*', '*', '*', 'moduleName=backup&methodName=backup', '备份数据和附件', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
('*/5', '*', '*', '*', '*', 'moduleName=mail&methodName=asyncSend', '异步发信', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
DROP TABLE IF EXISTS `zt_mailqueue`;
CREATE TABLE `zt_mailqueue` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`toList` varchar(255) NOT NULL,
`ccList` varchar(255) NOT NULL,
`subject` varchar(255) NOT NULL,
`body` text NOT NULL,
`addedBy` char(30) NOT NULL,
`addedDate` datetime NOT NULL,
`sendTime` datetime NOT NULL,
`status` varchar(10) NOT NULL DEFAULT 'wait',
`failReason` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

View File

@@ -17,9 +17,9 @@ class backup extends control
* @access public
* @return void
*/
public function __construct()
public function __construct($moduleName = '', $methodName = '')
{
parent::__construct();
parent::__construct($moduleName, $methodName);
$this->backupPath = $this->app->getTmpRoot() . 'backup/';
if(!is_dir($this->backupPath))
@@ -75,31 +75,52 @@ class backup extends control
* @access public
* @return void
*/
public function backup()
public function backup($reload = 'no')
{
set_time_limit(0);
$fileName = date('YmdHis') . mt_rand(0, 9);
$result = $this->backup->backSQL($this->backupPath . $fileName . '.sql.php');
if(!$result->result)
{
echo js::alert(sprintf($this->lang->backup->error->noWritable, $this->backupPath));
die(js::reload('parent'));
if($reload == 'yes')
{
echo js::alert(sprintf($this->lang->backup->error->noWritable, $this->backupPath));
die(js::reload('parent'));
}
else
{
printf($this->lang->backup->error->noWritable, $this->backupPath);
}
}
$this->backup->addFileHeader($this->backupPath . $fileName . '.sql.php');
if(extension_loaded('zlib'))
{
$result = $this->backup->backFile($this->backupPath . $fileName . '.file.zip.php');
if(!$result->result)
{
echo js::alert(sprintf($this->lang->backup->error->backupFile, $result->error));
die(js::reload('parent'));
}
$this->backup->addFileHeader($this->backupPath . $fileName . '.file.zip.php');
}
if(extension_loaded('zlib'))
{
$result = $this->backup->backFile($this->backupPath . $fileName . '.file.zip.php');
if(!$result->result)
{
if($reload == 'yes')
{
echo js::alert(sprintf($this->lang->backup->error->backupFile, $result->error));
die(js::reload('parent'));
}
else
{
printf($this->lang->backup->error->backupFile, $result->error);
}
}
$this->backup->addFileHeader($this->backupPath . $fileName . '.file.zip.php');
}
echo js::alert($this->lang->backup->success->backup);
die(js::reload('parent'));
if($reload == 'yes')
{
echo js::alert($this->lang->backup->success->backup);
die(js::reload('parent'));
}
else
{
echo $this->lang->backup->success->backup . "\n";
}
}
/**

View File

@@ -19,7 +19,7 @@
<div id='titlebar'>
<div class='heading'><?php echo $lang->backup->common;?></div>
<div class='actions'><?php common::printIcon('backup', 'backup', '', '', 'button', 'cloud', 'hiddenwin', 'backup');?></div>
<div class='actions'><?php common::printIcon('backup', 'backup', 'reload=yes', '', 'button', 'cloud', 'hiddenwin', 'backup');?></div>
</div>
<div class='panel'>
@@ -47,7 +47,7 @@
<?php if($i == 0):?>
<td <?php if($rowspan > 1) echo "rowspan='$rowspan'"?>>
<?php
if(common::hasPriv('backup', 'restore')) echo html::a(inlink('restore', "file=$backupFile->name"), $lang->backup->backup, 'hiddenwin', "class='restore'");
if(common::hasPriv('backup', 'restore')) echo html::a(inlink('restore', "file=$backupFile->name"), $lang->backup->restore, 'hiddenwin', "class='restore'");
if(common::hasPriv('backup', 'delete')) echo html::a(inlink('delete', "file=$backupFile->name"), $lang->delete, 'hiddenwin');
?>
</td>

View File

@@ -283,6 +283,7 @@ $lang->admin->menu->custom = array('link' => 'Custom|custom|index', 'subModul
$lang->admin->menu->mail = array('link' => 'Email|mail|index', 'subModule' => 'mail');
$lang->admin->menu->convert = array('link' => 'Import|convert|index', 'subModule' => 'convert');
$lang->admin->menu->backup = array('link' => 'Backup|backup|index', 'subModule' => 'backup');
$lang->admin->menu->cron = array('link' => 'Cron|cron|index', 'subModule' => 'cron');
$lang->admin->menu->trashes = array('link' => 'Trash|action|trash', 'subModule' => 'action');
$lang->admin->menu->dev = array('link' => 'Develop|dev|api', 'alias' => 'db', 'subModule' => 'dev,editor');
@@ -294,12 +295,14 @@ $lang->extension = new stdclass();
$lang->custom = new stdclass();
$lang->editor = new stdclass();
$lang->mail = new stdclass();
$lang->cron = new stdclass();
$lang->dev = new stdclass();
$lang->convert->menu = $lang->admin->menu;
$lang->upgrade->menu = $lang->admin->menu;
$lang->action->menu = $lang->admin->menu;
$lang->backup->menu = $lang->admin->menu;
$lang->cron->menu = $lang->admin->menu;
$lang->extension->menu = $lang->admin->menu;
$lang->custom->menu = $lang->admin->menu;
$lang->editor->menu = $lang->admin->menu;
@@ -325,6 +328,7 @@ $lang->menugroup->dept = 'company';
$lang->menugroup->todo = 'my';
$lang->menugroup->action = 'admin';
$lang->menugroup->backup = 'admin';
$lang->menugroup->cron = 'admin';
$lang->menugroup->extension = 'admin';
$lang->menugroup->custom = 'admin';
$lang->menugroup->editor = 'admin';

View File

@@ -112,9 +112,10 @@ $lang->admin->menuOrder[20] = 'editor';
$lang->admin->menuOrder[25] = 'mail';
$lang->admin->menuOrder[30] = 'custom';
$lang->admin->menuOrder[40] = 'convert';
$lang->admin->menuOrder[45] = 'backup';
$lang->admin->menuOrder[50] = 'dev';
$lang->admin->menuOrder[55] = 'trashes';
$lang->admin->menuOrder[45] = 'cron';
$lang->admin->menuOrder[50] = 'backup';
$lang->admin->menuOrder[55] = 'dev';
$lang->admin->menuOrder[60] = 'trashes';
$lang->convert->menuOrder = $lang->admin->menuOrder;
$lang->upgrade->menuOrder = $lang->admin->menuOrder;
$lang->action->menuOrder = $lang->admin->menuOrder;
@@ -124,4 +125,5 @@ $lang->editor->menuOrder = $lang->admin->menuOrder;
$lang->mail->menuOrder = $lang->admin->menuOrder;
$lang->custom->menuOrder = $lang->admin->menuOrder;
$lang->backup->menuOrder = $lang->admin->menuOrder;
$lang->cron->menuOrder = $lang->admin->menuOrder;
$lang->dev->menuOrder = $lang->admin->menuOrder;

View File

@@ -283,6 +283,7 @@ $lang->admin->menu->custom = array('link' => '自定义|custom|index', 'subMo
$lang->admin->menu->mail = array('link' => '发信|mail|index', 'subModule' => 'mail');
$lang->admin->menu->convert = array('link' => '导入|convert|index', 'subModule' => 'convert');
$lang->admin->menu->backup = array('link' => '备份|backup|index', 'subModule' => 'backup');
$lang->admin->menu->cron = array('link' => '计划任务|cron|index', 'subModule' => 'cron');
$lang->admin->menu->trashes = array('link' => '回收站|action|trash', 'subModule' => 'action');
$lang->admin->menu->dev = array('link' => '二次开发|dev|api', 'alias' => 'db', 'subModule' => 'dev,editor');
@@ -294,12 +295,14 @@ $lang->extension = new stdclass();
$lang->custom = new stdclass();
$lang->editor = new stdclass();
$lang->mail = new stdclass();
$lang->cron = new stdclass();
$lang->dev = new stdclass();
$lang->convert->menu = $lang->admin->menu;
$lang->upgrade->menu = $lang->admin->menu;
$lang->action->menu = $lang->admin->menu;
$lang->backup->menu = $lang->admin->menu;
$lang->cron->menu = $lang->admin->menu;
$lang->extension->menu = $lang->admin->menu;
$lang->custom->menu = $lang->admin->menu;
$lang->editor->menu = $lang->admin->menu;
@@ -325,6 +328,7 @@ $lang->menugroup->dept = 'company';
$lang->menugroup->todo = 'my';
$lang->menugroup->action = 'admin';
$lang->menugroup->backup = 'admin';
$lang->menugroup->cron = 'admin';
$lang->menugroup->extension = 'admin';
$lang->menugroup->custom = 'admin';
$lang->menugroup->editor = 'admin';

View File

@@ -21,6 +21,7 @@
<?php endif;?>
<?php
js::set('onlybody', $onlybody); // set the onlybody var.
if($this->loadModel('cron')->runable()) js::execute('startCron()');
if(isset($pageJS)) js::execute($pageJS); // load the js for current page.
/* Load hook files for current page. */

8
module/cron/config.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
$config->cron = new stdclass();
$config->cron->create = new stdclass();
$config->cron->edit = new stdclass();
$config->cron->create->requiredFields = 'm,h,dom,mon,dow,command';
$config->cron->edit->requiredFields = 'm,h,dom,mon,dow,command';
$config->cron->maxRunDays = 8;

216
module/cron/control.php Normal file
View File

@@ -0,0 +1,216 @@
<?php
/**
* The control file of cron of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package cron
* @version $Id$
* @link http://www.zentao.net
*/
class cron extends control
{
/**
* Index page.
*
* @access public
* @return void
*/
public function index()
{
$this->view->title = $this->lang->cron->common;
$this->view->position[] = $this->lang->cron->common;
$this->view->crons = $this->cron->getCrons();
$this->display();
}
/**
* Turnon cron.
*
* @access public
* @return void
*/
public function turnon()
{
$turnon = $this->config->global->cron ? 0 : 1;
$this->loadModel('setting')->setItem('system.common.global.cron', $turnon);
die(js::reload('parent'));
}
/**
* Create cron.
*
* @access public
* @return void
*/
public function create()
{
if($_POST)
{
$this->cron->create();
if(dao::isError()) die(js::error(dao::getError()));
die(js::locate(inlink('index'), 'parent'));
}
$this->view->title = $this->lang->cron->create . $this->lang->cron->common;
$this->view->position[] = html::a(inlink('index'), $this->lang->cron->common);
$this->view->position[] = $this->lang->cron->create;
$this->display();
}
/**
* Edit cron.
*
* @param int $cronID
* @access public
* @return void
*/
public function edit($cronID)
{
if($_POST)
{
$this->cron->update($cronID);
if(dao::isError()) die(js::error(dao::getError()));
die(js::locate(inlink('index'), 'parent'));
}
$this->view->title = $this->lang->cron->edit . $this->lang->cron->common;
$this->view->position[] = html::a(inlink('index'), $this->lang->cron->common);
$this->view->position[] = $this->lang->cron->edit;
$this->view->cron = $this->cron->getById($cronID);
$this->display();
}
/**
* Toggle run cron.
*
* @param int $cronID
* @param int $status
* @access public
* @return void
*/
public function toggle($cronID, $status)
{
$this->cron->changeStatus($cronID, $status);
die(js::reload('parent'));
}
/**
* Delete cron.
*
* @param int $cronID
* @param string $confirm
* @access public
* @return void
*/
public function delete($cronID, $confirm = 'no')
{
if($confirm == 'no') die(js::confirm($this->lang->cron->confirmDelete, inlink('delete', "cronID=$cronID&confirm=yes")));
$this->dao->delete()->from(TABLE_CRON)->where('id')->eq($cronID)->exec();
die(js::reload('parent'));
}
/**
* Ajax exec cron.
*
* @access public
* @return void
*/
public function ajaxExec()
{
ignore_user_abort(true);
set_time_limit(0);
session_write_close();
/* Check cron turnon. */
if(!$this->config->global->cron) die();
/* make cron status to running. */
$configID = $this->cron->getConfigID();
$configID = $this->cron->markCronStatus('running', $configID);
/* Get and parse crons. */
$crons = $this->cron->getCrons('nostop');
$parsedCrons = $this->cron->parseCron($crons);
/* Update last time. */
$this->cron->changeStatus(key($parsedCrons), 'normal', true);
$startedTime = time();
while(true)
{
/* When cron is null then die. */
if(empty($crons)) die();
if(empty($parsedCrons)) die();
/* Run crons. */
$now = new datetime('now');
foreach($parsedCrons as $id => $cron)
{
/* Skip stop and running cron.*/
$cronInfo = $this->cron->getById($id);
if(empty($cronInfo) or $cronInfo->status == 'stop' or $cronInfo->status == 'running') continue;
if($now > $cron['time'])
{
$this->cron->changeStatus($id, 'running');
$parsedCrons[$id]['time'] = $cron['cron']->getNextRunDate();
/* Execution command. */
$output = '';
$return = '';
if($cron['command'])
{
if(isset($crons[$id]) and $crons[$id]->type == 'zentao')
{
parse_str($cron['command'], $params);
if(isset($params['moduleName']) and isset($params['methodName']))
{
$output = $this->fetch($params['moduleName'], $params['methodName']);
}
}
elseif(isset($crons[$id]) and $crons[$id]->type == 'system')
{
exec($cron['command'], $output, $return);
if($output) $output = join("\n", $output);
}
}
/* Save log. */
if($output and $this->config->debug)
{
$log = '';
$time = $now->format('G:i:s');
$log = "$time task " . $id . " executed,\ncommand: $cron[command].\nreturn : $return.\noutput : $output\n";
$this->cron->logCron($log);
unset($log);
}
/* Revert cron status. */
$this->cron->changeStatus($id, 'normal');
}
}
/* Check whether the task change. */
$newCrons = $this->cron->getCrons('nostop');
$changed = $this->cron->checkChange();
if(count($newCrons) != count($crons) or $changed)
{
$crons = $newCrons;
$parsedCrons = $this->cron->parseCron($newCrons);
}
/* Sleep some seconds. */
$sleepTime = 60 - ((time() - $now->getTimestamp()) % 60);
sleep($sleepTime);
/* Break while. */
if(connection_status() != CONNECTION_NORMAL) break;
if(((time() - $startedTime) / 3600 / 24) >= $this->config->cron->maxRunDays) break;
}
/* Revert cron status to stop. */
$this->cron->markCronStatus('stop', $configID);
}
}

47
module/cron/lang/en.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
$lang->cron->common = 'Cron';
$lang->cron->index = 'Index';
$lang->cron->list = 'List';
$lang->cron->create = 'Create';
$lang->cron->edit = 'Edit';
$lang->cron->delete = 'Delete';
$lang->cron->toggle = 'Activation/Disable';
$lang->cron->turnon = 'Open/Close';
$lang->cron->m = 'Minute';
$lang->cron->h = 'Hour';
$lang->cron->dom = 'Day';
$lang->cron->mon = 'Month';
$lang->cron->dow = 'Week';
$lang->cron->command = 'Command';
$lang->cron->status = 'Status';
$lang->cron->type = 'Type';
$lang->cron->remark = 'Remark';
$lang->cron->lastTime = 'Last run time';
$lang->cron->turnonList['1'] = 'Open';
$lang->cron->turnonList['0'] = 'Close';
$lang->cron->statusList['normal'] = 'Normal';
$lang->cron->statusList['running'] = 'Running';
$lang->cron->statusList['stop'] = 'Stop';
$lang->cron->typeList['zentao'] = 'Self call';
$lang->cron->typeList['system'] = 'System command';
$lang->cron->toggleList['start'] = 'Activation';
$lang->cron->toggleList['stop'] = 'Disable';
$lang->cron->confirmDelete = 'Do you want to delete the task?';
$lang->cron->introduction = <<<EOD
<p>Timing tasks such as compute burn , backup. Absolve themselves of layout timing task.</p>
<p>This function has yet to be perfect, so the function is turned off by default</p>
<p>Whether to open the function? <a href="%s" target='hiddenwin'>Open timing task</a></p>
EOD;
$lang->cron->notice = new stdclass();
$lang->cron->notice->m = 'Range : 0-59"*" express the range of numbers, "/" express "Every", "-" express digital range.';
$lang->cron->notice->h = 'Range : 0-23';
$lang->cron->notice->dom = 'Range : 1-31';
$lang->cron->notice->mon = 'Range : 1-12';
$lang->cron->notice->dow = 'Range : 0-6';

View File

@@ -0,0 +1,47 @@
<?php
$lang->cron->common = '定时任务';
$lang->cron->index = '首页';
$lang->cron->list = '任务列表';
$lang->cron->create = '添加';
$lang->cron->edit = '编辑';
$lang->cron->delete = '删除';
$lang->cron->toggle = '激活/禁用';
$lang->cron->turnon = '打开/关闭';
$lang->cron->m = '分';
$lang->cron->h = '小时';
$lang->cron->dom = '天';
$lang->cron->mon = '月';
$lang->cron->dow = '周';
$lang->cron->command = '命令';
$lang->cron->status = '状态';
$lang->cron->type = '任务类型';
$lang->cron->remark = '备注';
$lang->cron->lastTime = '最后执行';
$lang->cron->turnonList['1'] = '打开';
$lang->cron->turnonList['0'] = '关闭';
$lang->cron->statusList['normal'] = '正常';
$lang->cron->statusList['running'] = '运行中';
$lang->cron->statusList['stop'] = '停止';
$lang->cron->typeList['zentao'] = '禅道自调用';
$lang->cron->typeList['system'] = '操作系统命令';
$lang->cron->toggleList['start'] = '激活';
$lang->cron->toggleList['stop'] = '禁用';
$lang->cron->confirmDelete = '是否删除该计划任务?';
$lang->cron->introduction = <<<EOD
<p>计划任务功能可以定时执行诸如更新燃尽图、备份等操作,免除自己布置定时任务。</p>
<p>该功能还有待完善,所以默认关闭该功能</p>
<p>是否开启该功能?<a href="%s" target='hiddenwin'>打开计划任务</a></p>
EOD;
$lang->cron->notice = new stdclass();
$lang->cron->notice->m = '取值范围:0-59"*"代表取值范围内的数字,"/"代表"每" "-"代表数字范围。';
$lang->cron->notice->h = '取值范围:0-23';
$lang->cron->notice->dom = '取值范围:1-31';
$lang->cron->notice->mon = '取值范围:1-12';
$lang->cron->notice->dow = '取值范围:0-6';

228
module/cron/model.php Normal file
View File

@@ -0,0 +1,228 @@
<?php
/**
* The model file of cron module of ZenTaoCMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package cron
* @version $Id$
* @link http://www.zentao.net
*/
class cronModel extends model
{
/**
* Get by Id.
*
* @param int $cronID
* @access public
* @return object
*/
public function getById($cronID)
{
return $this->dao->select('*')->from(TABLE_CRON)->where('id')->eq($cronID)->fetch();
}
/**
* Get crons.
*
* @param string $params
* @access public
* @return array
*/
public function getCrons($params = '')
{
return $this->dao->select('*')->from(TABLE_CRON)
->where('1=1')
->beginIF(strpos($params, 'nostop') !== false)->andWhere('status')->ne('stop')->fi()
->fetchAll('id');
}
/**
* Parse crons.
*
* @param array $crons
* @access public
* @return array
*/
public function parseCron($crons)
{
$this->app->loadClass('crontab', true);
$parsedCron = array();
foreach($crons as $cron)
{
$row = "{$cron->m} {$cron->h} {$cron->dom} {$cron->mon} {$cron->dow} {$cron->command}";
preg_match_all('/(\S+\s+){5}|.*/', $row, $matchs);
if($matchs[0])
{
try
{
$parsedCron = array();
$parsedCron['schema'] = trim($matchs[0][0]);
$parsedCron['command'] = trim($matchs[0][1]);
$parsedCron['cron'] = CronExpression::factory($parsedCron['schema']);
$parsedCron['time'] = $parsedCron['cron']->getNextRunDate();
$parsedCrons[$cron->id] = $parsedCron;
}
catch(InvalidArgumentException $e)
{
$this->dao->update(TABLE_CRON)->set('status')->eq('stop')->where('id')->eq($cron->id)->exec();
continue;
}
}
}
$this->dao->update(TABLE_CRON)->set('lastTime')->eq(date(DT_DATETIME1))->where('lastTime')->eq('0000-00-00 00:00:00')->andWhere('status')->ne('stop')->exec();
return $parsedCrons;
}
/**
* Change cron status.
*
* @param int $cronID
* @param string $status
* @param bool $changeTime
* @access public
* @return bool
*/
public function changeStatus($cronID, $status, $changeTime = false)
{
$data = new stdclass();
$data->status = $status;
if($status == 'running' or $changeTime) $data->lastTime = date(DT_DATETIME1);
$this->dao->update(TABLE_CRON)->data($data)->where('id')->eq($cronID)->exec();
return dao::isError() ? false : true;
}
/**
* Log cron.
*
* @param string $log
* @access public
* @return void
*/
public function logCron($log)
{
if(!is_writable($this->app->getLogRoot())) return false;
$file = $this->app->getLogRoot() . 'cron.' . date('Ymd') . '.log.php';
if(!is_file($file)) $log = "<?php\n die();\n" . $log;
$fp = fopen($file, "a");
fwrite($fp, $log);
fclose($fp);
}
/**
* Get last execed time.
*
* @access public
* @return string
*/
public function getLastTime()
{
return $this->dao->select('*')->from(TABLE_CRON)->orderBy('lastTime desc')->limit(1)->fetch('lastTime');
}
/**
* Runable cron.
*
* @access public
* @return bool
*/
public function runable()
{
if(!$this->config->global->cron) return false;
$lastTime = $this->getLastTime();
if($lastTime == '0000-00-00 00:00:00' or ((time() - strtotime($lastTime)) / 3600 > 1)) return true;
if(!isset($this->config->cron->run->status)) return true;
if($this->config->cron->run->status == 'stop') return true;
return false;
}
/**
* Check change cron.
*
* @access public
* @return bool
*/
public function checkChange()
{
$updatedCron = $this->dao->select('*')->from(TABLE_CRON)->where('lastTime')->eq('0000-00-00 00:00:00')->andWhere('status')->ne('stop')->fetch();
return $updatedCron ? true : false;
}
/**
* Create cron.
*
* @access public
* @return int
*/
public function create()
{
$cron = fixer::input('post')
->add('type', 'custom')
->add('status', 'normal')
->add('lastTime', '0000-00-00 00:00:00')
->skipSpecial('m,h,dom,mon,dow,command')
->get();
$this->dao->insert(TABLE_CRON)->data($cron)
->autoCheck()
->batchCheck($this->config->cron->create->requiredFields, 'notempty')
->exec();
return $this->dao->lastInsertID();
}
/**
* Update cron.
*
* @param int $cronID
* @access public
* @return bool
*/
public function update($cronID)
{
$cron = fixer::input('post')
->add('lastTime', '0000-00-00 00:00:00')
->skipSpecial('m,h,dom,mon,dow,command')
->get();
$this->dao->update(TABLE_CRON)->data($cron)
->autoCheck()
->batchCheck($this->config->cron->create->requiredFields, 'notempty')
->where('id')->eq($cronID)->exec();
return dao::isError() ? false : true;
}
public function markCronStatus($status, $configID = 0)
{
if($configID)
{
$this->dao->update(TABLE_CONFIG)->set('value')->eq($status)->where('id')->eq($configID)->exec();
return $configID;
}
else
{
$data = new stdclass();
$data->owner = 'system';
$data->module = 'cron';
$data->section = 'run';
$data->key = 'status';
$data->value = $status;
$this->dao->insert(TABLE_CONFIG)->data($data)->exec();
return $this->dao->lastInsertID();
}
}
public function getConfigID()
{
return $this->dao->select('*')->from(TABLE_CONFIG)
->where('owner')->eq('system')
->andWhere('module')->eq('cron')
->andWhere('section')->eq('run')
->andWhere('`key`')->eq('status')
->fetch('id');
}
}

View File

@@ -0,0 +1,68 @@
<?php
/**
* The index view file of cron module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package cron
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div class='container mw-700px'>
<div id='titlebar'>
<div class='heading'>
<strong><?php echo $lang->cron->common?></strong>
<small class'text-muted'> <?php echo $lang->cron->create?></small>
</div>
</div>
<form class='form-condensed' method='post' id='dataform' target='hiddenwin'>
<table class='table table-form'>
<tr>
<th class='rowhead w-80px'><?php echo $lang->cron->m;?></th>
<td class='w-p20'><?php echo html::input('m', '', "class='form-control'")?></td>
<td><?php echo $lang->cron->notice->m;?></td>
</tr>
<tr>
<th><?php echo $lang->cron->h;?></th>
<td><?php echo html::input('h', '', "class='form-control'")?></td>
<td><?php echo $lang->cron->notice->h;?></td>
</tr>
<tr>
<th><?php echo $lang->cron->dom;?></th>
<td><?php echo html::input('dom', '', "class='form-control'")?></td>
<td><?php echo $lang->cron->notice->dom;?></td>
</tr>
<tr>
<th><?php echo $lang->cron->mon;?></th>
<td><?php echo html::input('mon', '', "class='form-control'")?></td>
<td><?php echo $lang->cron->notice->mon;?></td>
</tr>
<tr>
<th><?php echo $lang->cron->dow;?></th>
<td><?php echo html::input('dow', '', "class='form-control'")?></td>
<td><?php echo $lang->cron->notice->dow;?></td>
</tr>
<tr>
<th><?php echo $lang->cron->command;?></th>
<td colspan='2'><?php echo html::input('command', '', "class='form-control'")?></td>
</tr>
<tr>
<th><?php echo $lang->cron->remark;?></th>
<td colspan='2'><?php echo html::input('remark', '', "class='form-control'")?></td>
</tr>
<tr>
<th><?php echo $lang->cron->type;?></th>
<td><?php echo html::select('type', $lang->cron->typeList, 'system', "class='form-control'")?></td>
</tr>
<tr>
<th></th>
<td><?php echo html::submitButton()?></td>
</tr>
</table>
</form>
</div>
<?php include '../../common/view/footer.html.php';?>

View File

@@ -0,0 +1,68 @@
<?php
/**
* The edit view file of cron module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package cron
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div class='container mw-700px'>
<div id='titlebar'>
<div class='heading'>
<strong><?php echo $lang->cron->common?></strong>
<small class'text-muted'> <?php echo $lang->cron->edit?></small>
</div>
</div>
<form class='form-condensed' method='post' id='dataform' target='hiddenwin'>
<table class='table table-form'>
<tr>
<th class='rowhead w-80px'><?php echo $lang->cron->m;?></th>
<td class='w-p20'><?php echo html::input('m', $cron->m, "class='form-control'")?></td>
<td><?php echo $lang->cron->notice->m;?></td>
</tr>
<tr>
<th><?php echo $lang->cron->h;?></th>
<td><?php echo html::input('h', $cron->h, "class='form-control'")?></td>
<td><?php echo $lang->cron->notice->h;?></td>
</tr>
<tr>
<th><?php echo $lang->cron->dom;?></th>
<td><?php echo html::input('dom', $cron->dom, "class='form-control'")?></td>
<td><?php echo $lang->cron->notice->dom;?></td>
</tr>
<tr>
<th><?php echo $lang->cron->mon;?></th>
<td><?php echo html::input('mon', $cron->mon, "class='form-control'")?></td>
<td><?php echo $lang->cron->notice->mon;?></td>
</tr>
<tr>
<th><?php echo $lang->cron->dow;?></th>
<td><?php echo html::input('dow', $cron->dow, "class='form-control'")?></td>
<td><?php echo $lang->cron->notice->dow;?></td>
</tr>
<tr>
<th><?php echo $lang->cron->command;?></th>
<td colspan='2'><?php echo html::input('command', str_replace("'", "&#039;", $cron->command), "class='form-control'")?></td>
</tr>
<tr>
<th><?php echo $lang->cron->remark;?></th>
<td colspan='2'><?php echo html::input('remark', $cron->remark, "class='form-control'")?></td>
</tr>
<tr>
<th><?php echo $lang->cron->type;?></th>
<td><?php echo html::select('type', $lang->cron->typeList, $cron->type, "class='form-control'")?></td>
</tr>
<tr>
<th></th>
<td><?php echo html::submitButton()?></td>
</tr>
</table>
</form>
</div>
<?php include '../../common/view/footer.html.php';?>

View File

@@ -0,0 +1,70 @@
<?php
/**
* The index view file of cron module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package cron
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='titlebar'>
<div class='heading'><?php echo $lang->cron->common;?></div>
<div class='actions'><?php if(common::hasPriv('cron', 'turnon') and $config->global->cron) echo html::a(inlink('turnon'), $lang->cron->turnonList[0] . $lang->cron->common, 'hiddenwin', "class='btn'");?></div>
</div>
<?php if($config->global->cron):?>
<div class='panel'>
<div class='panel-heading'>
<strong><?php echo $lang->cron->list?></strong>
<div class='panel-actions pull-right'><?php echo html::a(inlink('create'), $lang->cron->create, '', "class='btn btn-primary btn-sm'")?></div>
</div>
<table class='table table-condensed table-bordered active-disabled table-fixed'>
<thead>
<tr>
<th class='w-60px'><?php echo $lang->cron->m?></th>
<th class='w-60px'><?php echo $lang->cron->h?></th>
<th class='w-60px'><?php echo $lang->cron->dom?></th>
<th class='w-60px'><?php echo $lang->cron->mon?></th>
<th class='w-60px'><?php echo $lang->cron->dow?></th>
<th><?php echo $lang->cron->command?></th>
<th class='w-100px'><?php echo $lang->cron->remark?></th>
<th class='w-120px'><?php echo $lang->cron->lastTime?></th>
<th class='w-60px'><?php echo $lang->cron->status?></th>
<th class='w-100px'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody class='text-center'>
<?php foreach($crons as $cron):?>
<tr>
<td><?php echo $cron->m;?></td>
<td><?php echo $cron->h;?></td>
<td><?php echo $cron->dom;?></td>
<td><?php echo $cron->mon;?></td>
<td><?php echo $cron->dow;?></td>
<td class='text-left' title='<?php echo $cron->command?>'><?php echo $cron->command;?></td>
<td class='text-left' title='<?php echo $cron->remark?>'><?php echo $cron->remark;?></td>
<td><?php echo substr($cron->lastTime, 2);?></td>
<td><?php echo zget($lang->cron->statusList, $cron->status);?></td>
<td class='text-left'>
<?php
if(common::hasPriv('cron', 'toggle') and !empty($cron->command)) echo html::a(inlink('toggle', "id=$cron->id&status=" . ($cron->status == 'stop' ? 'normal' : 'stop')), $cron->status == 'stop' ? $lang->cron->toggleList['start'] : $lang->cron->toggleList['stop'], 'hiddenwin');
if($cron->buildin == 0 and common::hasPriv('cron', 'edit')) echo html::a(inlink('edit', "id=$cron->id"), $lang->edit);
if($cron->buildin == 0 and common::hasPriv('cron', 'delete')) echo html::a(inlink('delete', "id=$cron->id"), $lang->delete, 'hiddenwin');
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
<?php else:?>
<div class='container mw-700px'>
<div class='panel-body'><?php printf($lang->cron->introduction, inlink('turnon'))?></div>
</div>
<?php endif;?>
<?php include '../../common/view/footer.html.php';?>

View File

@@ -1,4 +1,5 @@
<?php
<<<<<<< HEAD
$lang->dev->common = 'Develop';
$lang->dev->api = 'API';
$lang->dev->db = 'Database';
@@ -79,3 +80,18 @@ $lang->dev->tableList['svn'] = 'SVN';
$lang->dev->tableList['testcase'] = 'Testcase';
$lang->dev->tableList['tree'] = 'Tree';
$lang->dev->tableList['upgrade'] = 'Upgrade';
=======
$lang->dev->common = 'Dev';
$lang->dev->api = 'API';
$lang->dev->db = 'Database';
$lang->dev->editor = 'Editor';
$lang->dev->dbList = 'Datebases';
$lang->dev->fields = array();
$lang->dev->fields['id'] = 'ID';
$lang->dev->fields['name'] = 'Field';
$lang->dev->fields['desc'] = 'Desc';
$lang->dev->fields['type'] = 'Type';
$lang->dev->fields['length'] = 'Length';
$lang->dev->fields['null'] = 'Empty';
>>>>>>> fdc283afd74c3cf379fd24153ece79fe519c0b20

View File

@@ -424,8 +424,19 @@ class extension extends control
{
$tmpName = $_FILES['file']['tmp_name'];
$fileName = $_FILES['file']['name'];
$extension = basename($fileName, '.zip');
move_uploaded_file($tmpName, $this->app->getTmpRoot() . "/extension/$fileName");
$extension = basename($fileName, '.zip');
$return = $this->extension->extractPackage($extension);
if($return->result != 'ok') die(js::alert(sprintf($this->lang->extension->errorExtracted, $packageFile, $return->error)));
$info = $this->extension->parseExtensionCFG($extension);
if(isset($info->code) and $info->code != $extension)
{
$classFile = $this->app->loadClass('zfile');
$classFile->removeDir("ext/$extension");
$extension = $info->code;
}
$info = $this->extension->getInfoFromDB($extension);
$type = $info->status == 'installed' ? 'upgrade' : 'install';
$link = $type == 'install' ? inlink('install', "extension=$extension") : inlink('upgrade', "extension=$extension");

View File

@@ -82,6 +82,8 @@ class gitModel extends model
public function run()
{
$this->setRepos();
if(empty($this->repos)) return false;
$this->setLogRoot();
$this->setRestartFile();
@@ -90,11 +92,13 @@ class gitModel extends model
$this->printLog("begin repo $name");
$repo = (object)$repo;
$repo->name = $name;
$this->setRepo($repo);
if(!$this->setRepo($repo)) return false;
$savedRevision = $this->getSavedRevision();
$this->printLog("start from revision $savedRevision");
$logs = $this->getRepoLogs($repo, $savedRevision);
if(empty($logs)) return false;
$this->printLog("get " . count($logs) . " logs");
if(empty($logs)) continue;
@@ -171,12 +175,18 @@ class gitModel extends model
* Set the repos.
*
* @access public
* @return void
* @return bool
*/
public function setRepos()
{
if(!$this->config->git->repos) die("You must set one git repo.\n");
if(!$this->config->git->repos)
{
echo "You must set one git repo.\n";
return false;
}
$this->repos = $this->config->git->repos;
return true;
}
/**
@@ -184,13 +194,16 @@ class gitModel extends model
*
* @param object $repo
* @access public
* @return void
* @return bool
*/
public function setRepo($repo)
{
$this->setClient($repo);
if(empty($this->client)) return false;
$this->setLogFile($repo->name);
$this->setRepoRoot($repo);
return true;
}
/**
@@ -198,12 +211,18 @@ class gitModel extends model
*
* @param object $repo
* @access public
* @return void
* @return bool
*/
public function setClient($repo)
{
if($this->config->git->client == '') die("You must set the git client file.\n");
if($this->config->git->client == '')
{
echo "You must set the git client file.\n";
return false;
}
$this->client = $this->config->git->client;
return true;
}
/**
@@ -253,7 +272,11 @@ class gitModel extends model
}
exec($cmd, $list, $return);
if(!$list and $return) die("Some error occers: \nThe command is $cmd\n");
if(!$list and $return)
{
echo "Some error occers: \nThe command is $cmd\n";
return false;
}
if(!$list and !$return) return array();
/* Process logs. */
@@ -375,6 +398,7 @@ class gitModel extends model
if(!$repo) return false;
$this->setClient($repo);
if(empty($this->client)) return false;
putenv('LC_CTYPE=en_US.UTF-8');
$path = str_replace('%2F', '/', urlencode($path));
@@ -399,6 +423,7 @@ class gitModel extends model
if(!$repo) return false;
$this->setClient($repo);
if(empty($this->client)) return false;
putenv('LC_CTYPE=en_US.UTF-8');

View File

@@ -53,6 +53,8 @@ $lang->moduleOrder[155] = 'api';
$lang->moduleOrder[160] = 'file';
$lang->moduleOrder[165] = 'misc';
$lang->moduleOrder[170] = 'backup';
$lang->moduleOrder[175] = 'cron';
$lang->moduleOrder[180] = 'dev';
$lang->resource = new stdclass();
@@ -535,6 +537,9 @@ $lang->resource->mail->edit = 'edit';
$lang->resource->mail->save = 'save';
$lang->resource->mail->test = 'test';
$lang->resource->mail->reset = 'reset';
$lang->resource->mail->browse = 'browse';
$lang->resource->mail->delete = 'delete';
$lang->resource->mail->batchDelete = 'batchDelete';
$lang->mail->methodOrder[5] = 'index';
$lang->mail->methodOrder[10] = 'detect';
@@ -542,6 +547,9 @@ $lang->mail->methodOrder[15] = 'edit';
$lang->mail->methodOrder[20] = 'save';
$lang->mail->methodOrder[25] = 'test';
$lang->mail->methodOrder[30] = 'reset';
$lang->mail->methodOrder[35] = 'browse';
$lang->mail->methodOrder[40] = 'delete';
$lang->mail->methodOrder[45] = 'batchDelete';
/* custom. */
$lang->resource->custom = new stdclass();
@@ -825,6 +833,28 @@ $lang->backup->methodOrder[10] = 'backup';
$lang->backup->methodOrder[15] = 'restore';
$lang->backup->methodOrder[20] = 'delete';
$lang->resource->cron = new stdclass();
$lang->resource->cron->index = 'index';
$lang->resource->cron->turnon = 'turnon';
$lang->resource->cron->create = 'create';
$lang->resource->cron->edit = 'edit';
$lang->resource->cron->toggle = 'toggle';
$lang->resource->cron->delete = 'delete';
$lang->cron->methodOrder[5] = 'index';
$lang->cron->methodOrder[10] = 'turnon';
$lang->cron->methodOrder[15] = 'create';
$lang->cron->methodOrder[20] = 'edit';
$lang->cron->methodOrder[25] = 'toggle';
$lang->cron->methodOrder[30] = 'delete';
$lang->resource->dev = new stdclass();
$lang->resource->dev->api = 'api';
$lang->resource->dev->db = 'db';
$lang->dev->methodOrder[5] = 'api';
$lang->dev->methodOrder[10] = 'db';
/* Every version of new privilege. */
$lang->changelog['1.0.1'][] = 'project-computeBurn';
@@ -1015,3 +1045,13 @@ $lang->changelog['6.4'][] = 'release-linkBug';
$lang->changelog['6.4'][] = 'release-unlinkBug';
$lang->changelog['6.4'][] = 'release-batchUnlinkBug';
$lang->changelog['6.4'][] = 'story-batchAssignTo';
$lang->changelog['7.1'][] = 'cron-index';
$lang->changelog['7.1'][] = 'cron-turnon';
$lang->changelog['7.1'][] = 'cron-create';
$lang->changelog['7.1'][] = 'cron-edit';
$lang->changelog['7.1'][] = 'cron-toggle';
$lang->changelog['7.1'][] = 'cron-delete';
$lang->changelog['7.1'][] = 'mail-browse';
$lang->changelog['7.1'][] = 'mail-delete';
$lang->changelog['7.1'][] = 'mail-batchDelete';

View File

@@ -17,9 +17,9 @@ class mail extends control
* @access public
* @return void
*/
public function __construct()
public function __construct($moduleName = '', $methodName = '')
{
parent::__construct();
parent::__construct($moduleName, $methodName);
/* Task #1967. check the function of fsocket. */
if(!function_exists('fsockopen'))
@@ -121,6 +121,7 @@ class mail extends control
$mailConfig->turnon = $this->post->turnon;
$mailConfig->mta = 'smtp';
$mailConfig->async = $this->post->async;
$mailConfig->fromAddress = trim($this->post->fromAddress);
$mailConfig->fromName = trim($this->post->fromName);
$mailConfig->smtp->host = trim($this->post->host);
@@ -218,4 +219,100 @@ class mail extends control
$this->dao->delete('*')->from(TABLE_CONFIG)->where('module')->eq('mail')->exec();
$this->locate(inlink('detect'));
}
/**
* Async send mail.
*
* @access public
* @return void
*/
public function asyncSend()
{
$queueList = $this->mail->getQueue('wait', 'id_asc');
$now = helper::now();
if(isset($this->config->mail->async))$this->config->mail->async = 0;
foreach($queueList as $queue)
{
$this->mail->send($queue->toList, $queue->subject, $queue->body, $queue->ccList);
$data = new stdclass();
$data->sendTime = $now;
$data->status = 'send';
if($this->mail->isError())
{
$data->status = 'fail';
$data->failReason = join("\n", $this->mail->getError());
}
$this->dao->update(TABLE_MAILQUEUE)->data($data)->where('id')->eq($queue->id)->exec();
$log = "Send #$query->id result is $data->status\n";
if($data->status == 'fail') $log .= "reason is $data->failReason\n";
echo $log;
}
echo "OK\n";
}
/**
* Browse mail queue.
*
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 100, $pageID = 1)
{
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$this->view->title = $this->lang->mail->browse;
$this->view->position[] = html::a(inlink('edit'), $this->lang->mail->common);
$this->view->position[] = $this->lang->mail->browse;
$this->view->queueList = $this->mail->getQueue(null, $orderBy, $pager);
$this->view->pager = $pager;
$this->view->orderBy = $orderBy;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
}
/**
* Delete mail queue.
*
* @param int $id
* @param string $confirm
* @access public
* @return void
*/
public function delete($id, $confirm = 'no')
{
if($confirm == 'no') die(js::confirm($this->lang->mail->confirmDelete, inlink('delete', "id=$id&confirm=yes")));
$this->dao->delete()->from(TABLE_MAILQUEUE)->where('id')->eq($id)->exec();
die(js::reload('parent'));
}
/**
* Batch delete mail queue.
*
* @param string $confirm
* @access public
* @return void
*/
public function batchDelete($confirm = 'no')
{
if($confirm == 'no')
{
if(empty($_POST)) die(js::reload('parent'));
$idList = join('|', $this->post->mailIDList);
die(js::confirm($this->lang->mail->confirmDelete, inlink('batchDelete', "confirm=yes") . ($this->config->requestType == 'GET' ? '&' : '?') . "idList=$idList"));
}
$idList = array();
if(isset($_GET['idList'])) $idList = explode(',', $_GET['idList']);
if($idList) $this->dao->delete()->from(TABLE_MAILQUEUE)->where('id')->in($idList)->exec();
die(js::reload('parent'));
}
}

View File

@@ -6,8 +6,12 @@ $lang->mail->edit = 'Configure';
$lang->mail->save = 'Successfully saved';
$lang->mail->test = 'Testing';
$lang->mail->reset = 'Reset';
$lang->mail->browse = 'Mail list';
$lang->mail->delete = 'Delete mail';
$lang->mail->batchDelete = 'Batch delete';
$lang->mail->turnon = 'Turnon';
$lang->mail->async = 'Asynchronous';
$lang->mail->fromAddress = 'From email';
$lang->mail->fromName = 'From title';
$lang->mail->mta = 'MTA';
@@ -20,9 +24,24 @@ $lang->mail->secure = 'Secure';
$lang->mail->debug = 'Debug';
$lang->mail->charset = 'Charset';
$lang->mail->toList = 'Addressee';
$lang->mail->subjectName = 'Subject';
$lang->mail->addedBy = 'Sender';
$lang->mail->addedDate = 'Added date';
$lang->mail->sendTime = 'Send time';
$lang->mail->status = 'Status';
$lang->mail->ccList = 'Copy to';
$lang->mail->failReason = 'Fail Reason';
$lang->mail->statusList['send'] = 'Success';
$lang->mail->statusList['fail'] = 'Fail';
$lang->mail->turnonList[1] = 'on';
$lang->mail->turnonList[0] = 'off';
$lang->mail->asyncList[1] = 'Yes';
$lang->mail->asyncList[0] = 'No';
$lang->mail->debugList[0] = 'off';
$lang->mail->debugList[1] = 'normal';
$lang->mail->debugList[2] = 'high';
@@ -40,8 +59,8 @@ $lang->mail->successSaved = 'The configuration has been successfully saved.';
$lang->mail->subject = "It's a testing email from zentao.";
$lang->mail->content = 'If you can see this, the email notification feature can work now!';
$lang->mail->successSended = 'Successfully sended!';
$lang->mail->confirmDelete = 'Confirm delete mail?';
$lang->mail->sendmailTips = 'Tips: system will not send mail to current user.';
$lang->mail->needConfigure = "I can not find the configuration, please configure it first.";
$lang->mail->nofsocket = 'The fsocket correlation function is disabled, not letter! Please enlarge the setting of allow_url_fopen to On in php.ini and open the extension of openssl. Restart apache.';
$lang->mail->noOpenssl = 'Please open the extension of openssl when use tls. Restart apache.';
$lang->mail->noCurl = 'Please open the extension of curl when use tls and ssl. Restart apache.';

View File

@@ -6,8 +6,12 @@ $lang->mail->edit = '编辑配置';
$lang->mail->save = '成功保存';
$lang->mail->test = '测试发信';
$lang->mail->reset = '重置';
$lang->mail->browse = '邮件列表';
$lang->mail->delete = '删除邮件';
$lang->mail->batchDelete = '批量删除';
$lang->mail->turnon = '是否打开';
$lang->mail->async = '异步发送';
$lang->mail->fromAddress = '发信邮箱';
$lang->mail->fromName = '发信人';
$lang->mail->mta = '发信方式';
@@ -20,9 +24,24 @@ $lang->mail->secure = '是否加密';
$lang->mail->debug = '调试级别';
$lang->mail->charset = '编码';
$lang->mail->toList = '收信人';
$lang->mail->subjectName = '主题';
$lang->mail->addedBy = '发送者';
$lang->mail->addedDate = '创建时间';
$lang->mail->sendTime = '发送时间';
$lang->mail->status = '状态';
$lang->mail->ccList = '抄送给';
$lang->mail->failReason = '失败原因';
$lang->mail->statusList['send'] = '成功';
$lang->mail->statusList['fail'] = '失败';
$lang->mail->turnonList[1] = '打开';
$lang->mail->turnonList[0] = '关闭';
$lang->mail->asyncList[1] = '是';
$lang->mail->asyncList[0] = '否';
$lang->mail->debugList[0] = '关闭';
$lang->mail->debugList[1] = '一般';
$lang->mail->debugList[2] = '较高';
@@ -40,6 +59,7 @@ $lang->mail->successSaved = '配置信息已经成功保存。';
$lang->mail->subject = '测试邮件';
$lang->mail->content = '邮箱设置成功';
$lang->mail->successSended = '成功发送!';
$lang->mail->confirmDelete = '是否删除邮件?';
$lang->mail->sendmailTips = '提示:系统不会为当前操作者发信。';
$lang->mail->needConfigure = '无法找到邮件配置信息,请先配置邮件发送参数。';
$lang->mail->nofsocket = 'fsocket相关函数被禁用不能发信请在php.ini中修改allow_url_fopen为On打开openssl扩展。 保存并重新启动apache。';

View File

@@ -242,6 +242,7 @@ class mailModel extends model
public function send($toList, $subject, $body = '', $ccList = '', $includeMe = false)
{
if(!$this->config->mail->turnon) return;
if(isset($this->config->mail->async) and $this->config->mail->async) return $this->addQueue($toList, $subject, $body, $ccList, $includeMe);
ob_start();
$toList = $toList ? explode(',', str_replace(' ', '', $toList)) : array();
@@ -436,4 +437,58 @@ class mailModel extends model
$this->errors = array();
return $errors;
}
/**
* Add queue.
*
* @param string $toList
* @param string $subject
* @param string $body
* @param string $ccList
* @param bool $includeMe
* @access public
* @return void
*/
public function addQueue($toList, $subject, $body = '', $ccList = '', $includeMe = false)
{
$toList = $toList ? explode(',', str_replace(' ', '', $toList)) : array();
$ccList = $ccList ? explode(',', str_replace(' ', '', $ccList)) : array();
/* Process toList and ccList, remove current user from them. If toList is empty, use the first cc as to. */
if($includeMe == false)
{
$account = isset($this->app->user->account) ? $this->app->user->account : '';
foreach($toList as $key => $to) if(trim($to) == $account or !trim($to)) unset($toList[$key]);
foreach($ccList as $key => $cc) if(trim($cc) == $account or !trim($cc)) unset($ccList[$key]);
}
$toList = join(',', $toList);
$ccList = join(',', $ccList);
$data = new stdclass();
$data->toList = $toList;
$data->ccList = $ccList;
$data->subject = $subject;
$data->body = $body;
$data->addedBy = $this->app->user->account;
$data->addedDate = helper::now();
$this->dao->insert(TABLE_MAILQUEUE)->data($data)->autocheck()->batchCheck('toList,subject', 'notempty')->exec();
}
/**
* Get queue.
*
* @param string $status
* @access public
* @return array
*/
public function getQueue($status = '', $orderBy = 'id_desc', $pager = null)
{
return $this->dao->select('*')->from(TABLE_MAILQUEUE)
->where('1=1')
->beginIF($status)->andWhere('status')->eq($status)->fi()
->orderBy($orderBy)
->page($pager)
->fetchAll();
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* The browse view file of mail module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package mail
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='titlebar'>
<div class='heading'><?php echo $lang->mail->browse?></div>
</div>
<form method='post' action='<?php echo inlink('batchDelete')?>' target='hiddenwin'>
<div class='panel'>
<table class='table table-condensed table-bordered active-disabled table-fixed tablesorter'>
<?php $vars = "orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"; ?>
<thead>
<tr>
<th class='w-id'> <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
<th class='w-80px'> <?php common::printOrderLink('toList', $orderBy, $vars, $lang->mail->toList);?></th>
<th class='w-150px'> <?php common::printOrderLink('subject', $orderBy, $vars, $lang->mail->subjectName);?></th>
<th class='w-80px'> <?php common::printOrderLink('addedBy', $orderBy, $vars, $lang->mail->addedBy);?></th>
<th class='w-150px'> <?php common::printOrderLink('addedDate', $orderBy, $vars, $lang->mail->addedDate);?></th>
<th class='w-150px'> <?php common::printOrderLink('sendTime', $orderBy, $vars, $lang->mail->sendTime);?></th>
<th class='w-60px'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->mail->status);?></th>
<th> <?php echo $lang->mail->failReason;?></th>
<th class='w-80px'> <?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody class='text-center'>
<?php foreach($queueList as $queue):?>
<tr>
<td>
<input type='checkbox' name='mailIDList[]' value='<?php echo $queue->id;?>'/>
<?php echo $queue->id?>
</td>
<td><?php echo zget($users, $queue->toList, $queue->toList)?></td>
<td class='text-left'><?php echo $queue->subject?></td>
<td><?php echo zget($users, $queue->addedBy, $queue->addedBy)?></td>
<td><?php echo $queue->addedDate?></td>
<td><?php echo $queue->sendTime?></td>
<td><?php echo zget($lang->mail->statusList, $queue->status)?></td>
<td class='text-left'><?php echo $queue->failReason?></td>
<td><?php if(common::hasPriv('mail', 'delete')) echo html::a(inlink('delete', "id=$queue->id"), $lang->delete, 'hiddenwin');?></td>
</tr>
<?php endforeach;?>
</tbody>
<tfoot>
<tr>
<td colspan='9'>
<?php
if(count($queueList))
{
echo "<div class='btn-group'>" . html::selectButton() . '</div>';
if(common::hasPriv('mail', 'batchDelete')) echo html::submitButton($lang->delete);
}
$pager->show();
?>
</td>
</tr>
</tfoot>
</table>
</div>
</form>
<?php include '../../common/view/footer.html.php';?>

View File

@@ -25,6 +25,12 @@ include '../../common/view/header.html.php';
<th class='rowhead w-120px'><?php echo $lang->mail->turnon; ?></th>
<td><?php echo html::radio('turnon', $lang->mail->turnonList, 1);?></td>
</tr>
<?php if($config->global->cron):?>
<tr>
<th class='text-top'><?php echo $lang->mail->async?></th>
<td><?php echo html::radio('async', $lang->mail->asyncList, zget($config->mail, 'async', 0))?></td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->mail->fromAddress; ?></th>
<td><?php echo html::input('fromAddress', $mailConfig->fromAddress, "class='form-control'");?></td>
@@ -72,6 +78,7 @@ include '../../common/view/header.html.php';
echo html::submitButton();
if($this->config->mail->turnon and $mailExist) echo html::linkButton($lang->mail->test, inlink('test'));
echo html::linkButton($lang->mail->reset, inlink('reset'));
if(common::hasPriv('mail', 'browse') and isset($config->mail->async) and $config->mail->async and $config->global->cron) echo html::linkButton($lang->mail->browse, inlink('browse'));
?>
</td>
</tr>

View File

@@ -1,51 +1,51 @@
<?php
/**
* The html template file of index method of index module of ZenTaoPMS.
*
<?php
/**
* The html template file of index method of index module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package ZenTaoPMS
* @version $Id: index.html.php 1947 2011-06-29 11:58:03Z wwccss $
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/sparkline.html.php';?>
<?php css::import($defaultTheme . 'index.css', $config->version);?>
<div class="row">
<div class="col-md-8">
<?php include './blockprojects.html.php';?>
<?php include './blockproducts.html.php';?>
</div>
<div class="col-md-4">
<?php if(common::hasPriv('company', 'dynamic')) include './blockdynamic.html.php';?>
</div>
</div>
<div class="row">
<div class="col-md-4 col-sm-6">
<?php include './blocktodoes.html.php';?>
</div>
<?php if($app->user->role and strpos('qa|qd', $app->user->role) !== false):?>
<div class="col-md-4 col-sm-6">
<?php include './blockbugs.html.php';?>
</div>
<div class="col-md-4 col-sm-6">
<?php include './blocktasks.html.php';?>
</div>
<?php elseif($app->user->role and strpos('po|pd', $app->user->role) !== false):?>
<div class="col-md-4 col-sm-6">
<?php include './blockstories.html.php';?>
</div>
<div class="col-md-4 col-sm-6">
<?php include './blockbugs.html.php';?>
</div>
<?php else:?>
<div class="col-md-4 col-sm-6">
<?php include './blocktasks.html.php';?>
</div>
<div class="col-md-4 col-sm-6">
<?php include './blockbugs.html.php';?>
</div>
<?php endif;?>
</div>
<?php include '../../common/view/footer.html.php';?>
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package ZenTaoPMS
* @version $Id: index.html.php 1947 2011-06-29 11:58:03Z wwccss $
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/sparkline.html.php';?>
<?php css::import($defaultTheme . 'index.css', $config->version);?>
<div class="row">
<div class="col-md-8">
<?php include './blockprojects.html.php';?>
<?php include './blockproducts.html.php';?>
</div>
<div class="col-md-4">
<?php if(common::hasPriv('company', 'dynamic')) include './blockdynamic.html.php';?>
</div>
</div>
<div class="row">
<div class="col-md-4 col-sm-6">
<?php include './blocktodoes.html.php';?>
</div>
<?php if($app->user->role and strpos('qa|qd', $app->user->role) !== false):?>
<div class="col-md-4 col-sm-6">
<?php include './blockbugs.html.php';?>
</div>
<div class="col-md-4 col-sm-6">
<?php include './blocktasks.html.php';?>
</div>
<?php elseif($app->user->role and strpos('po|pd', $app->user->role) !== false):?>
<div class="col-md-4 col-sm-6">
<?php include './blockstories.html.php';?>
</div>
<div class="col-md-4 col-sm-6">
<?php include './blockbugs.html.php';?>
</div>
<?php else:?>
<div class="col-md-4 col-sm-6">
<?php include './blocktasks.html.php';?>
</div>
<div class="col-md-4 col-sm-6">
<?php include './blockbugs.html.php';?>
</div>
<?php endif;?>
</div>
<?php include '../../common/view/footer.html.php';?>

View File

@@ -18,9 +18,9 @@ class project extends control
* @access public
* @return void
*/
public function __construct()
public function __construct($moduleName = '', $methodName = '')
{
parent::__construct();
parent::__construct($moduleName, $methodName);
if($this->methodName != 'computeburn')
{
$this->projects = $this->project->getPairs('nocode');
@@ -789,7 +789,7 @@ class project extends control
{
$this->view->burns = $this->project->computeBurn();
if($reload == 'yes') die(js::reload('parent'));
die($this->display());
$this->display();
}
/**

View File

@@ -91,6 +91,6 @@
$headerHooks = glob(dirname(dirname(__FILE__)) . "/ext/view/featurebar.*.html.hook.php");
if(!empty($headerHooks))
{
foreach($headerHooks as $fileName) helper::import($fileName);
foreach($headerHooks as $fileName) include($fileName);
}
?>

0
module/report/ext/control/.gitkeep Normal file → Executable file
View File

0
module/report/ext/lang/zh-cn/.gitkeep Normal file → Executable file
View File

0
module/report/ext/model/.gitkeep Normal file → Executable file
View File

0
module/report/ext/view/.gitkeep Normal file → Executable file
View File

View File

@@ -82,6 +82,8 @@ class svnModel extends model
public function run()
{
$this->setRepos();
if(empty($this->repos)) return false;
$this->setLogRoot();
$this->setRestartFile();
@@ -90,11 +92,13 @@ class svnModel extends model
$this->printLog("begin repo $name");
$repo = (object)$repo;
$repo->name = $name;
$this->setRepo($repo);
if(!$this->setRepo($repo)) return false;
$savedRevision = $this->getSavedRevision();
$this->printLog("start from revision $savedRevision");
$logs = $this->getRepoLogs($repo, $savedRevision);
if(empty($logs)) return false;
$this->printLog("get " . count($logs) . " logs");
$this->printLog('begin parsing logs');
@@ -169,12 +173,18 @@ class svnModel extends model
* Set the repos.
*
* @access public
* @return void
* @return bool
*/
public function setRepos()
{
if(!$this->config->svn->repos) die("You must set one svn repo.\n");
if(!$this->config->svn->repos)
{
echo "You must set one svn repo.\n";
return false;
}
$this->repos = $this->config->svn->repos;
return true;
}
/**
@@ -182,13 +192,16 @@ class svnModel extends model
*
* @param object $repo
* @access public
* @return void
* @return bool
*/
public function setRepo($repo)
{
$this->setClient($repo);
if(empty($this->client)) return false;
$this->setLogFile($repo->name);
$this->setRepoRoot($repo);
return true;
}
/**
@@ -196,11 +209,16 @@ class svnModel extends model
*
* @param object $repo
* @access public
* @return void
* @return bool
*/
public function setClient($repo)
{
if($this->config->svn->client == '') die("You must set the svn client file.\n");
if($this->config->svn->client == '')
{
echo "You must set the svn client file.\n";
return false;
}
$this->client = $this->config->svn->client . " --non-interactive";
if(stripos($repo->path, 'https') === 0 or stripos($repo->path, 'svn') === 0)
{
@@ -212,6 +230,7 @@ class svnModel extends model
}
}
if(isset($repo->username)) $this->client .= " --username $repo->username --password $repo->password --no-auth-cache";
return true;
}
/**
@@ -258,7 +277,11 @@ class svnModel extends model
$cmd = $this->client . " log -r $fromRevision:HEAD -v --xml $repo->path";
$rawLogs = `$cmd`;
$logs = @simplexml_load_string($rawLogs); // Convert it to object.
if(!$logs) die("Some error occers: \nThe command is $cmd\n the svn logs is $rawLogs\n");
if(!$logs)
{
echo "Some error occers: \nThe command is $cmd\n the svn logs is $rawLogs\n";
return false;
}
/* Process logs. */
foreach($logs->logentry as $entry) $parsedLogs[] = $this->convertLog($entry);
@@ -367,6 +390,7 @@ class svnModel extends model
if(!$repo) return false;
$this->setClient($repo);
if(empty($this->client)) return false;
putenv('LC_CTYPE=en_US.UTF-8');
$oldRevision = $revision - 1;
@@ -393,6 +417,7 @@ class svnModel extends model
if(!$repo) return false;
$this->setClient($repo);
if(empty($this->client)) return false;
putenv('LC_CTYPE=en_US.UTF-8');

View File

@@ -1100,6 +1100,7 @@ class task extends control
/* Set related files. */
if(isset($relatedFiles[$task->id]))
{
$task->files = '';
foreach($relatedFiles[$task->id] as $file)
{
$fileURL = 'http://' . $this->server->http_host . $this->config->webRoot . "data/upload/{$this->app->company->id}/" . $file->pathname;

View File

@@ -60,6 +60,6 @@
$headerHooks = glob(dirname(dirname(__FILE__)) . "/ext/view/featurebar.*.html.hook.php");
if(!empty($headerHooks))
{
foreach($headerHooks as $fileName) helper::import($fileName);
foreach($headerHooks as $fileName) include($fileName);
}
?>

View File

@@ -43,6 +43,6 @@
$headerHooks = glob(dirname(dirname(__FILE__)) . "/ext/view/featurebar.*.html.hook.php");
if(!empty($headerHooks))
{
foreach($headerHooks as $fileName) helper::import($fileName);
foreach($headerHooks as $fileName) include($fileName);
}
?>

View File

@@ -1178,6 +1178,15 @@ function fixStyle()
if($actions.length) $('#titlebar > .heading').css('padding-right', $actions.width());
}
function startCron()
{
$.ajax({
type: "GET",
timeout: 100,
url: createLink('cron', 'ajaxExec')
});
}
/* Ping the server every some minutes to keep the session. */
needPing = true;