Merge branch 'master' of ssh://172.20.0.1/var/git/espo/backend

This commit is contained in:
Yuri Kuznetsov
2014-03-21 15:23:44 +02:00
13 changed files with 310 additions and 89 deletions

View File

@@ -1,7 +1,5 @@
<?php
error_reporting(0);
require_once('../../bootstrap.php');
$app = new \Espo\Core\Application();

View File

@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -18,12 +18,12 @@
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
************************************************************************/
namespace Espo\Core\Loaders;
use Espo\Core\Utils;
use Monolog\Handler;
use Espo\Core\Utils,
Espo\Core\Utils\Log\Monolog\Handler;
class Log
{
@@ -41,12 +41,11 @@ class Log
public function load()
{
$config = $this->getContainer()->get('config');
$logConfig = $this->getContainer()->get('config')->get('logger');
$logConfig = $config->get('logger');
$log = new Utils\Log('Espo');
$levelCode = $log->getLevelCode($logConfig['level']);
$log = new Utils\Log('Espo');
$levelCode = $log->getLevelCode($logConfig['level']);
if ($logConfig['isRotate']) {
$handler = new Handler\RotatingFileHandler($logConfig['path'], $logConfig['maxRotateFiles'], $levelCode);
@@ -54,7 +53,11 @@ class Log
$handler = new Handler\StreamHandler($logConfig['path'], $levelCode);
}
$log->pushHandler($handler);
\Monolog\ErrorHandler::register($log);
$errorHandler = new \Monolog\ErrorHandler($log);
$errorHandler->registerExceptionHandler(null, false);
$errorHandler->registerErrorHandler(array(), false);
$errorHandler->registerFatalHandler();
return $log;
}

View File

@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -18,7 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
************************************************************************/
namespace Espo\Core\Utils\Database\Orm;
@@ -45,14 +45,14 @@ class Converter
);
/*
* //pair espo:doctrine
* //pair Espo => ORM
*/
protected $fieldAccordances = array(
'type' => 'type',
'dbType' => 'dbType',
'maxLength' => 'len',
'len' => 'len',
'notnull' => 'notnull',
'notNull' => 'notNull',
'autoincrement' => 'autoincrement',
'notStorable' => 'notStorable',
'link' => 'relation',
@@ -60,7 +60,7 @@ class Converter
'unique' => 'unique',
'index' => 'index',
/*'conditions' => 'conditions',
'additionalColumns' => 'additionalColumns', */
'additionalColumns' => 'additionalColumns', */
'default' => array(
'condition' => '^javascript:',
'conditionEquals' => false,
@@ -199,7 +199,7 @@ class Converter
case 'foreignId':
$fieldParams = array_merge($fieldParams, $this->idParams);
$fieldParams['notnull'] = false;
$fieldParams['notNull'] = false;
break;
case 'foreignType':
@@ -304,12 +304,12 @@ class Converter
$fieldParams = Util::merge($fieldParams, $fieldTypeMeta['database']);
}
//if defined 'notnull => false' and 'required => true', then remove 'notnull'
if (isset($fieldParams['notnull']) && !$fieldParams['notnull'] && isset($fieldParams['required']) && $fieldParams['required']) {
unset($fieldParams['notnull']);
} //END
//if defined 'notNull => false' and 'required => true', then remove 'notNull'
if (isset($fieldParams['notNull']) && !$fieldParams['notNull'] && isset($fieldParams['required']) && $fieldParams['required']) {
unset($fieldParams['notNull']);
} //END
$fieldDefs = $this->getInitValues($fieldParams);
//check if field need to be saved in database
@@ -448,23 +448,23 @@ class Converter
protected function getInitValues(array $fieldParams)
{
$values = array();
foreach($this->fieldAccordances as $espoType => $doctrineType) {
foreach($this->fieldAccordances as $espoType => $ormType) {
if (isset($fieldParams[$espoType])) {
if (is_array($doctrineType)) {
if (is_array($ormType)) {
$conditionRes = false;
if (!is_array($fieldParams[$espoType])) {
$conditionRes = preg_match('/'.$doctrineType['condition'].'/i', $fieldParams[$espoType]);
$conditionRes = preg_match('/'.$ormType['condition'].'/i', $fieldParams[$espoType]);
}
if (!$conditionRes || ($conditionRes && $conditionRes === $doctrineType['conditionEquals']) ) {
if (!$conditionRes || ($conditionRes && $conditionRes === $ormType['conditionEquals']) ) {
$value = is_array($fieldParams[$espoType]) ? json_encode($fieldParams[$espoType]) : $fieldParams[$espoType];
$values = Util::merge( $values, Util::replaceInArray('{0}', $value, $doctrineType['value']) );
$values = Util::merge( $values, Util::replaceInArray('{0}', $value, $ormType['value']) );
}
} else {
$values[$doctrineType] = $fieldParams[$espoType];
$values[$ormType] = $fieldParams[$espoType];
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -18,7 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
************************************************************************/
namespace Espo\Core\Utils\Database\Orm\Fields;
@@ -36,8 +36,8 @@ class LinkParent extends \Espo\Core\Utils\Database\Orm\Base
),
$field['name'].'Type' => array(
'type' => 'foreignType',
'notnull' => false,
'index' => $field['name'],
'notNull' => false,
'index' => $field['name'],
),
$field['name'].'Name' => array(
'type' => 'varchar',

View File

@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -18,7 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
************************************************************************/
namespace Espo\Core\Utils\Database\Orm\Fields;
@@ -29,35 +29,42 @@ class PersonName extends \Espo\Core\Utils\Database\Orm\Base
public function load($entity, $field)
{
$foreignField = $this->getForeignField($field['name'], $entity['name']);
$foreignField = $this->getForeignField($field['name'], $entity['name']);
$tableName = Util::toUnderScore($entity['name']);
$fullList = array(); //contains empty string (" ") like delimiter
$fullListReverse = array(); //reverse of $fullList
$fieldList = array(); //doesn't contain empty string (" ") like delimiter
$like = array();
$equal = array();
foreach($foreignField as $fieldName) {
$fieldNameTrimmed = trim($fieldName);
$fieldNameTrimmed = trim($fieldName);
if (!empty($fieldNameTrimmed)) {
$columnName = $tableName.'.'.Util::toUnderScore($fieldNameTrimmed);
$fullList[] = $fieldList[] = $columnName;
$fullList[] = $fieldList[] = $columnName;
$like[] = $columnName." LIKE '{text}'";
$equal[] = $columnName." = '{text}'";
} else {
$fullList[] = "'".$fieldName."'";
$fullList[] = "'".$fieldName."'";
}
}
return array(
$fullListReverse = array_reverse($fullList);
return array(
$entity['name'] => array (
'fields' => array(
$field['name'] => array(
'type' => 'varchar',
'fields' => array(
$field['name'] => array(
'type' => 'varchar',
'select' => "TRIM(CONCAT(".implode(", ", $fullList)."))",
'where' => array(
'LIKE' => "(".implode(" OR ", $like)." OR CONCAT(".implode(", ", $fullList).") LIKE '{text}')",
),
'orderBy' => implode(", ", array_map(function ($item) {return $item . ' {direction}';}, $fieldList)),
'where' => array(
'LIKE' => "(".implode(" OR ", $like)." OR CONCAT(".implode(", ", $fullList).") LIKE '{text}' OR CONCAT(".implode(", ", $fullListReverse).") LIKE '{text}')",
'=' => "(".implode(" OR ", $equal)." OR CONCAT(".implode(", ", $fullList).") = '{text}' OR CONCAT(".implode(", ", $fullListReverse).") = '{text}')",
),
'orderBy' => implode(", ", array_map(function ($item) {return $item . ' {direction}';}, $fieldList)),
),
),
),

View File

@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -18,7 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
************************************************************************/
namespace Espo\Core\Utils\Database\Schema;
@@ -35,11 +35,11 @@ class Converter
protected $typeList;
//pair espo::doctrine
//pair ORM => doctrine
protected $allowedDbFieldParams = array(
'len' => 'length',
'default' => 'default',
'notnull' => 'notnull',
'notNull' => 'notnull',
'autoincrement' => 'autoincrement',
'unique' => 'unique',
);
@@ -87,14 +87,14 @@ class Converter
$GLOBALS['log']->debug('Schema\Converter - Start: building schema');
//check if exist files in "Tables" directory and merge with ormMetadata
$ormMeta = Util::merge($ormMeta, $this->getCustomTables());
$ormMeta = Util::merge($ormMeta, $this->getCustomTables());
//unset some keys in orm
if (isset($ormMeta['unset'])) {
$ormMeta = Util::unsetInArray($ormMeta, $ormMeta['unset']);
unset($ormMeta['unset']);
} //END: unset some keys in orm
$schema = $this->getSchema();
@@ -115,7 +115,7 @@ class Converter
switch ($fieldParams['type']) {
case 'id':
$primaryColumns[] = Util::toUnderScore($fieldName);
break;
break;
}
$fieldType = isset($fieldParams['dbType']) ? $fieldParams['dbType'] : $fieldParams['type'];
@@ -130,13 +130,13 @@ class Converter
}
//add unique
if ($fieldParams['type']!= 'id' && isset($fieldParams['unique'])) {
if ($fieldParams['type']!= 'id' && isset($fieldParams['unique'])) {
$uniqueColumns = $this->getKeyList($columnName, $fieldParams['unique'], $uniqueColumns);
} //END: add unique
//add index. It can be defined in entityDefs as "index"
if (isset($fieldParams['index'])) {
$indexList = $this->getKeyList($columnName, $fieldParams['index'], $indexList);
$indexList = $this->getKeyList($columnName, $fieldParams['index'], $indexList);
} //END: add index
}
@@ -150,8 +150,8 @@ class Converter
if (!empty($uniqueColumns)) {
foreach($uniqueColumns as $uniqueItem) {
$tables[$entityName]->addUniqueIndex($uniqueItem);
}
}
}
}
}
//check and create columns/tables for relations
@@ -171,7 +171,7 @@ class Converter
if (!isset($tables[$tableName])) { //no needs to create the table if it already exists
$tables[$tableName] = $this->prepareManyMany($entityName, $relationParams, $tables);
}
break;
break;
case 'belongsTo':
$foreignEntity = $relationParams['entity'];
@@ -288,8 +288,8 @@ class Converter
/**
* Get key list (index, unique). Ex. index => true OR index => 'somename'
* @param string $columnName Column name (underscore field name)
* @param bool | string $keyValue
* @return array
* @param bool | string $keyValue
* @return array
*/
protected function getKeyList($columnName, $keyValue, array $keyList)
{
@@ -314,7 +314,7 @@ class Converter
foreach($fileList as $fileName) {
$fileData = $this->getFileManager()->getContents( array($this->customTablePath, $fileName) );
if (is_array($fileData)) {
if (is_array($fileData)) {
$customTables = Util::merge($customTables, $fileData);
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php
/************************************************************************
* This file is part of EspoCRM.
*
@@ -18,32 +18,13 @@
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
************************************************************************/
namespace Espo\Core\Utils;
class Log extends \Monolog\Logger
use Espo\Core\Utils\Log\Monolog\Logger;
class Log extends Logger
{
protected $defaultLevelName = 'DEBUG';
/**
* Get Level Code
* @param string $level Ex. DEBUG, ...
* @return int
*/
public function getLevelCode($levelName)
{
$levelName = strtoupper($levelName);
$levels = $this->getLevels();
if (isset($levels[$levelName])) {
return $levels[$levelName];
}
return $levels[$this->defaultLevelName];
}
}

View File

@@ -0,0 +1,117 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
namespace Espo\Core\Utils\Log\Monolog\Handler;
use Monolog\Logger;
class RotatingFileHandler extends StreamHandler
{
/**
* Date format as a part of filename
* @var string
*/
protected $dateFormat = 'Y-m-d';
/**
* Filename format
* @var string
*/
protected $filenameFormat = '{filename}-{date}';
protected $filename;
protected $maxFiles;
public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true)
{
$this->filename = $filename;
$this->maxFiles = (int) $maxFiles;
parent::__construct($this->getTimedFilename(), $level, $bubble);
$this->rotate();
}
public function setFilenameFormat($filenameFormat, $dateFormat)
{
$this->filenameFormat = $filenameFormat;
$this->dateFormat = $dateFormat;
}
protected function rotate()
{
if (0 === $this->maxFiles) {
return; //unlimited number of files for 0
}
$filePattern = $this->getFilePattern();
$dirPath = $this->getFileManager()->getDirName($this->filename);
$logFiles = $this->getFileManager()->getFileList($dirPath, false, $filePattern, 'file');
if (!empty($logFiles) && count($logFiles) > $this->maxFiles) {
usort($logFiles, function($a, $b) {
return strcmp($b, $a);
});
$logFilesToBeRemoved = array_slice($logFiles, $this->maxFiles);
$this->getFileManager()->removeFiles($logFilesToBeRemoved, $dirPath);
}
}
protected function getTimedFilename()
{
$fileInfo = pathinfo($this->filename);
$timedFilename = str_replace(
array('{filename}', '{date}'),
array($fileInfo['filename'], date($this->dateFormat)),
$fileInfo['dirname'] . '/' . $this->filenameFormat
);
if (!empty($fileInfo['extension'])) {
$timedFilename .= '.'.$fileInfo['extension'];
}
return $timedFilename;
}
protected function getFilePattern()
{
$fileInfo = pathinfo($this->filename);
$glob = str_replace(
array('{filename}', '{date}'),
array($fileInfo['filename'], '.*'),
$this->filenameFormat
);
if (!empty($fileInfo['extension'])) {
$glob .= '\.'.$fileInfo['extension'];
}
$glob = '^'.$glob.'$';
return $glob;
}
}

View File

@@ -0,0 +1,66 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
namespace Espo\Core\Utils\Log\Monolog\Handler;
use Monolog\Logger;
class StreamHandler extends \Monolog\Handler\StreamHandler
{
protected $fileManager;
public function __construct($url, $level = Logger::DEBUG, $bubble = true)
{
parent::__construct($url, $level, $bubble);
$this->fileManager = new \Espo\Core\Utils\File\Manager();
}
protected function getFileManager()
{
return $this->fileManager;
}
protected function write(array $record)
{
if (!$this->url) {
throw new \LogicException('Missing logger path, the stream can not be opened. Please check logger options in the data/config.php.');
}
$this->errorMessage = null;
set_error_handler(array($this, 'customErrorHandler'));
$this->getFileManager()->appendContents($this->url, (string) $record['formatted']);
restore_error_handler();
if (isset($this->errorMessage)) {
throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage, $this->url));
}
}
private function customErrorHandler($code, $msg)
{
$this->errorMessage = $msg;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: http://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
************************************************************************/
namespace Espo\Core\Utils\Log\Monolog;
class Logger extends \Monolog\Logger
{
protected $defaultLevelName = 'DEBUG';
/**
* Get Level Code
* @param string $level Ex. DEBUG, ...
* @return int
*/
public function getLevelCode($levelName)
{
$levelName = strtoupper($levelName);
$levels = $this->getLevels();
if (isset($levels[$levelName])) {
return $levels[$levelName];
}
return $levels[$this->defaultLevelName];
}
}

View File

@@ -23,6 +23,6 @@
"advanced":true
},
"database":{
"notnull":false
"notNull":false
}
}

View File

@@ -23,6 +23,6 @@
"advanced":false
},
"database":{
"notnull":false
"notNull":false
}
}

View File

@@ -23,6 +23,6 @@
"advanced":true
},
"database":{
"notnull":false
"notNull":false
}
}