Skip to content

Commit 627d5e4

Browse files
committed
initial commit
0 parents  commit 627d5e4

12 files changed

Lines changed: 607 additions & 0 deletions

File tree

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# CakePHPLog plugin for CakePHP
2+
3+
## Installation
4+
5+
You can install this plugin into your CakePHP application using [composer](https://getcomposer.org).
6+
7+
The recommended way to install composer packages is:
8+
9+
```
10+
composer require tyrellsys/cakephp-log
11+
```
12+
13+
## Usage
14+
15+
### Formatter::getMessage($message)
16+
17+
convert `$message` to string.
18+
19+
```
20+
[hostname]:/path/to/filename(line no)[pid]: extracted $message
21+
```
22+
23+
24+
```
25+
...
26+
use Tyrellsys\CakePHPLog\Formatter;
27+
...
28+
$message = string / array / Cake\Datasource\EntityInterface / Object
29+
30+
Log::write(LOG_WARNING, Formatter::getMessage($message));
31+
Log::info(Formatter::getMessage($message));
32+
$this->log(Formatter::getMessage($message), LOG_WARNING);
33+
34+
```
35+
36+
## Override CakePHP4 Cake\Log\Log and Cake\Log\LogTrait
37+
38+
https://book.cakephp.org/4/en/appendices/4-0-migration-guide.html#log
39+
> Logging related methods like Cake\Log\LogTrait::log(), Cake\Log\Log::write() etc. now only accept string for $message argument. This change was necessary to align the API with PSR-3 standard.
40+
41+
*You understand and use the feature to ignore the change.*
42+
43+
44+
Tyrellsys\CakePHP\Log
45+
```
46+
...
47+
use Tyrellsys\CakePHPLog\Log;
48+
...
49+
Log::write(LOG_WARNING, $mixed); // mixed message with Tyrellsys/CakePHPLog/Formatter::getMessage()
50+
...
51+
```
52+
53+
Tyrellsys\CakePHPLog\LogTrait
54+
```
55+
...
56+
use Tyrellsys\CakePHPLog\LogTrait;
57+
...
58+
class XXX
59+
{
60+
use Tyrellsys\CakePHPLog/LogTrait;
61+
...
62+
$this->log($mixed, LOG_WARNING); // mixed message with Tyrellsys/CakePHPLog/Formatter::getMessage()
63+
...
64+
}
65+
...
66+
```

composer.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "tyrellsys/cakephp-log",
3+
"description": "CakePHPLog plugin for CakePHP",
4+
"type": "cakephp-plugin",
5+
"license": "MIT",
6+
"require": {
7+
"cakephp/cakephp": "^4.0"
8+
},
9+
"require-dev": {
10+
"phpunit/phpunit": "^8.0"
11+
},
12+
"autoload": {
13+
"psr-4": {
14+
"Tyrellsys\\CakePHPLog\\": "src/"
15+
}
16+
},
17+
"autoload-dev": {
18+
"psr-4": {
19+
"Tyrellsys\\CakePHPLog\\Test\\": "tests/",
20+
"Cake\\Test\\": "vendor/cakephp/cakephp/tests/"
21+
}
22+
}
23+
}

phpunit.xml.dist

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit
3+
colors="true"
4+
processIsolation="false"
5+
stopOnFailure="false"
6+
bootstrap="tests/bootstrap.php"
7+
>
8+
<php>
9+
<ini name="memory_limit" value="-1"/>
10+
<ini name="apc.enable_cli" value="1"/>
11+
</php>
12+
13+
<!-- Add any additional test suites you want to run here -->
14+
<testsuites>
15+
<testsuite name="CakePHPLog">
16+
<directory>tests/TestCase/</directory>
17+
</testsuite>
18+
</testsuites>
19+
20+
<!-- Setup a listener for fixtures -->
21+
<listeners>
22+
<listener class="Cake\TestSuite\Fixture\FixtureInjector">
23+
<arguments>
24+
<object class="Cake\TestSuite\Fixture\FixtureManager"/>
25+
</arguments>
26+
</listener>
27+
</listeners>
28+
29+
<filter>
30+
<whitelist>
31+
<directory suffix=".php">src/</directory>
32+
</whitelist>
33+
</filter>
34+
35+
</phpunit>

src/Formatter.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Tyrellsys\CakePHPLog;
5+
6+
use Cake\Datasource\EntityInterface;
7+
use Cake\Error\Debugger;
8+
use JsonSerializable;
9+
10+
class Formatter
11+
{
12+
/**
13+
* @param string|array $data data
14+
* @return string
15+
*/
16+
public static function getMessage($data): string
17+
{
18+
$isArray = is_array($data);
19+
20+
$data = (array)$data;
21+
22+
$result = [];
23+
foreach ($data as $key => $record) {
24+
if (is_string($record)) {
25+
$result[$key] = $record;
26+
continue;
27+
}
28+
29+
$isObject = is_object($record);
30+
31+
if ($isObject && $record instanceof EntityInterface) {
32+
$result[$key] = json_encode($record, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
33+
continue;
34+
}
35+
36+
if ($isObject && method_exists($record, '__toString')) {
37+
$result[$key] = (string)$record;
38+
continue;
39+
}
40+
41+
if ($isObject && $record instanceof JsonSerializable) {
42+
$result[$key] = json_encode($record, JSON_UNESCAPED_UNICODE);
43+
continue;
44+
}
45+
46+
$result[$key] = print_r($record, true);
47+
}
48+
49+
$message = static::_prefix();
50+
if ($isArray) {
51+
$message .= print_r($result, true);
52+
} else {
53+
$message .= current($result);
54+
}
55+
$message .= static::_suffix();
56+
57+
return $message;
58+
}
59+
60+
/**
61+
*
62+
* @return string
63+
*/
64+
protected static function _prefix(): string
65+
{
66+
$traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
67+
$found = null;
68+
$dirname = dirname(__DIR__);
69+
$length = strlen($dirname);
70+
$before = null;
71+
foreach ($traces as $trace) {
72+
if (substr($trace['file'], 0, $length) !== $dirname) {
73+
$found = preg_match('#^' . preg_quote(APP) . '#', $trace['file']) ? $trace : $before;
74+
break;
75+
}
76+
$before = $trace;
77+
}
78+
79+
// [hostname]:path/to/caller_filename:[caller line no](pid):
80+
return '[' . php_uname('n') . ']:' .
81+
Debugger::trimPath($found['file']) .
82+
'(' . $found['line'] . ')' .
83+
'[' . getmypid() . ']: ';
84+
}
85+
86+
/**
87+
*
88+
* @return string
89+
*/
90+
protected static function _suffix(): string
91+
{
92+
return "";
93+
}
94+
}

src/Log.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Tyrellsys\CakePHPLog;
5+
6+
use Cake\Log\Log as CakeLog;
7+
use Tyrellsys\CakePHPLog\Formatter;
8+
9+
class Log
10+
{
11+
const WRITER_METHODS = [
12+
'emergency',
13+
'alert',
14+
'critical',
15+
'error',
16+
'warning',
17+
'notice',
18+
'info',
19+
'debug',
20+
];
21+
22+
/**
23+
* __callStatic php's magic method
24+
*
25+
* Proxy for Cake\Log\Log method
26+
*
27+
* @return mixed
28+
*/
29+
public static function __callStatic(string $name, array $arguments)
30+
{
31+
if ($name === 'write') {
32+
return CakeLog::write($arguments[0], Formatter::getMessage($arguments[1]), $arguments[2] ?? []);
33+
} elseif (in_array($name, self::WRITER_METHODS, true)) {
34+
return CakeLog::{$name}(Formatter::getMessage($arguments[0]), $arguments[1] ?? []);
35+
} else {
36+
return CakeLog::{$name}(...$arguments);
37+
}
38+
}
39+
}
40+

src/LogTrait.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Tyrellsys\CakePHPLog;
5+
6+
use Cake\Log\Log;
7+
use Psr\Log\LogLevel;
8+
use Tyrellsys\CakePHPLog\Formatter;
9+
10+
/**
11+
* A trait providing an object short-cut method
12+
* to logging.
13+
*/
14+
trait LogTrait
15+
{
16+
17+
/**
18+
* Convenience method to write a message to Log. See Log::write()
19+
* for more information on writing to logs.
20+
*
21+
* @param string $message Log message.
22+
* @param int|string $level Error level.
23+
* @param string|array $context Additional log data relevant to this message.
24+
* @return bool Success of log write.
25+
*/
26+
public function log($message, $level = LogLevel::ERROR, $context = []): bool
27+
{
28+
return Log::write($level, Formatter::getMessage($message), $context);
29+
}
30+
}
31+

src/Plugin.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Tyrellsys\CakePHPLog;
5+
6+
use Cake\Core\BasePlugin;
7+
8+
/**
9+
* Plugin for CakePHPLog
10+
*/
11+
class Plugin extends BasePlugin
12+
{
13+
}

0 commit comments

Comments
 (0)