Skip to content

Commit d4c5820

Browse files
committed
Releasing 1.0.4
2 parents 052395f + a8082a5 commit d4c5820

File tree

10 files changed

+589
-36
lines changed

10 files changed

+589
-36
lines changed

README.md

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ This is a collection of useful classes and functions for every day PHP life. It
66
* Logging to error_log with different levels
77
* Notification to users across various requests within a session
88
* Extracting information from the current HTTP request
9+
* Obfuscating sensitive information to protect data against spambots
10+
* Slugifying strings for usage in URLs
911
* Generating random strings
12+
* Formatting prices and units
1013

1114
These classes are no rocket science, just simple helpers that prevent from wiriting the
1215
same code in various flavours over and over again.
@@ -80,8 +83,13 @@ Logging is very simple. Set your log level (if not INFO) and start logging:
8083
```
8184
use TgLog\Log;
8285
83-
// Set the log level
84-
Log::setLogLevel(Log::ERROR);
86+
// Set default settings before using the log:
87+
Log::setDefaultLogLevel(Log::ERROR);
88+
Log::setDefaultAppName('MyApplication');
89+
90+
// Or just on the singleton logging instance
91+
Log::instance()->setLogLevel(Log::ERROR);
92+
Log::instance()->setAppName('MyAppName');
8593
8694
// Simple line
8795
Log::error('A simple error message');
@@ -116,6 +124,16 @@ $stacktrace = Log::getStackTrace();
116124
Log::infoStackTrace();
117125
```
118126

127+
Finally, you can create your special instances of a log for some modules and log from there, e.g.
128+
129+
```
130+
$moduleLog = new Log(Log::ERROR, 'MyAppModule');
131+
132+
$moduleLog->logInfo('Module started');
133+
$moduleLog->logError('Exception occurred:', $exception);
134+
135+
```
136+
119137
## User Notifications
120138

121139
Sometimes it is hard to display success or error messages because the message needs to
@@ -159,11 +177,58 @@ A simple authentication helper interface along with a default implementation is
159177
* [TgUtils\Auth\CredentialsProvider](https://github.com/technicalguru/php-utils/blob/src/TgUtils/Auth/CredentialsProvider.php) - Interface to provide username and password to other objects
160178
* [TgUtils\Auth\DefaultCredentialsProvider](https://github.com/technicalguru/php-utils/blob/src/TgUtils/Auth/DefaultCredentialsProvider.php) - Simple default implementation of the interface
161179

180+
## Sensitive Data Obfuscation
181+
182+
Publishing sensitive data such as e-mail addresses and phone numbers is dangerous nowadays as spammers
183+
grab such information automatically from websites. The utils package provides a javascript-based way
184+
to obfuscate this information on websites. Its' idea is based on the rot13 obfuscation method but uses a
185+
random character mapping instead of a fixed rotation. This idea was chosen because rot13 seems to be a kind of standard
186+
in obfuscation and spammers might already be able to read them.
187+
188+
It shall be noted that it is still not impossible to read the information even when obfuscated. But it requires
189+
a bit more sophisticated effort (Javascript execution) to gain the sensitive information.
190+
191+
**Idea:** The text to be obfuscated is replaced - char by char - by other characters from a map. This map is
192+
generated uniquely for this special obfuscation instance. Other obfuscations on the same page will use different
193+
maps. The HTML source displays only: `[javascript protected]`. However, a special javascript will run after
194+
the page loaded and replace exactly this text with the real content.
195+
196+
Two obfuscation methods exists: a simple text obfuscation and an e-mail obfuscation which also creates a mailto: link
197+
that the user can click.
198+
199+
Here is how you use it:
200+
201+
```
202+
user \TgUtils\Obfuscation;
203+
204+
/*** Just create everything and put it in your HTML page **/
205+
$htmlSource = Obfuscation::obfuscateText('+49 555 0123456');
206+
$emailLink = Obfuscation::obfuscateEmail('[email protected]');
207+
208+
/*************************** OR ***************************/
209+
// Use your own tag ID
210+
$id = Obfuscation::generateObfuscationId();
211+
212+
// Use this ID to get the bot-resistent HTML source
213+
$htmlSource = Obfuscation::getObfuscatedHtmlSpan($id);
214+
215+
// And get the javascript
216+
$textJavascript = Obfuscation::obfuscateText('+49 555 0123456', $id);
217+
$emailJavascript = Obfuscation::obfuscateEmail('[email protected]', $id);
218+
219+
```
220+
221+
Please notice that not all characters are supported in the default character map. It covers mainly
222+
e-mail addresses and phone numbers. However, you can pass your own character set to the obfuscate methods
223+
as third argument. Please consult the [source code](https://github.com/technicalguru/php-utils/blob/src/TgUtils/Obfuscation.php) for more details.
224+
162225
## Other Utils
163226
There are some daily tasks that need to be done in applications. The `Utils` class addresses a few of them:
164227

165228
```
166229
use TgUtils\Utils;
230+
use TgUtils\FormatUtils;
231+
use TgUtils\Slugify;
167232
168233
// create a random string
169234
$myId = Utils::generateRandomString(20);
@@ -188,6 +253,15 @@ $allNames = Utils::extractAttributeFromList($objectList, 'name');
188253
189254
// Mask a sensitive string
190255
$masked = Utils::anonymize($aPhoneNumber);
256+
257+
// Slugify a string
258+
$slug = Slugify::slugify('A text that turn into an URL');
259+
260+
// Format a price
261+
$priceString = FormatUtils::formatPrice(3000.643, 'EUR');
262+
263+
// Format a file size
264+
$fileSize = FormatUtils::formatUnit(3000643, 'B');
191265
```
192266

193267
Inspect the [source code](https://github.com/technicalguru/php-utils/blob/src/TgUtils/Utils.php) to find more about the methods available.

src/TgLog/Log.php

Lines changed: 102 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,76 @@ class Log {
2121
/** The available log priorities */
2222
protected static $logPriorities;
2323
/** The log level to issue in error_log */
24-
protected static $logLevel;
24+
protected static $defaultLogLevel;
25+
/** The name of the application to prefix log entries */
26+
protected static $defaultAppName;
2527

2628
/** The single instance of the log */
2729
public static $instance;
2830

2931
/** All log messages that were issued */
3032
public $messages;
33+
/** The log level of the instance */
34+
protected $logLevel;
35+
/** The app name to prefix lof entries with */
36+
protected $appName;
3137

3238
/**
3339
* Returns the single instance.
3440
* @return Log - single Log instance
3541
*/
3642
public static function instance() {
37-
if (self::$logLevel == null) {
38-
self::$logLevel == self::INFO;
43+
if (self::$defaultLogLevel == null) {
44+
self::$defaultLogLevel = self::INFO;
3945
}
4046
if (self::$instance == null) {
41-
self::$instance = new Log();
47+
self::$instance = new Log(self::$defaultLogLevel, self::$defaultAppName);
4248
}
4349
return self::$instance;
4450
}
4551

52+
/**
53+
* Returns the log level of this instance.
54+
* @return string the current log level
55+
*/
56+
public function getLogLevel() {
57+
return $this->logLevel;
58+
}
59+
60+
/**
61+
* Sets the log level of this instance.
62+
* @param string $level - the new log level
63+
*/
64+
public function setLogLevel($level) {
65+
$this->logLevel = $level;
66+
}
67+
68+
/**
69+
* Returns the prefix for log entries.
70+
* @return string the current prefix
71+
*/
72+
public function getAppName() {
73+
return $this->appName;
74+
}
75+
76+
/**
77+
* Sets the prefix that log entries shall be given.
78+
* @param string $appName - the new prefix
79+
*/
80+
public function setAppName($appName) {
81+
$this->appName = $appName;
82+
}
83+
4684
/**
4785
* Public constructor.
86+
* @param string $logLevel - the log level for this instance (optional, default is Log::INFO)
87+
* @param string $appName - the prefix for the log entry (optional)
4888
* <p>Usually you don't need to instantiate it yourself but use the single instance.</p>
4989
*/
50-
public function __construct() {
90+
public function __construct($logLevel = self::INFO, $appName = NULL) {
5191
$this->messages = array();
92+
$this->logLevel = $logLevel;
93+
$this->appName = $appName != NULL ? $appName : self::$defaultAppName;
5294
}
5395

5496
/**
@@ -67,7 +109,8 @@ protected function log($sev, $s, $o = null) {
67109
}
68110
}
69111
$this->messages[$sev][] = $s;
70-
if (self::isLogLevelIncluded($sev)) error_log('[WebApp - '.strtoupper($sev).'] '.$s);
112+
$prefix = $this->getAppName() != NULL ? '['.$this->getAppName().']' : '';
113+
if ($this->isLogLevelIncluded($sev)) error_log($prefix.'['.strtoupper($sev).'] '.$s);
71114
}
72115

73116
/**
@@ -78,7 +121,7 @@ protected function log($sev, $s, $o = null) {
78121
public function logStackTrace($sev, $excludeFile = NULL) {
79122
$trace = $this->getStackTrace($excludeFile);
80123
$this->log($sev, 'Stacktrace:');
81-
foreach ($trace AS $idx => $line) {
124+
foreach ($trace AS $line) {
82125
$this->log($sev, ' '.$line);
83126
}
84127
}
@@ -109,7 +152,16 @@ public function getStackTrace($excludeFile = NULL) {
109152
* @param mixed $o - an oject to be dumped along with message. An Exception object will cause a stacktrace dump (optional).
110153
*/
111154
public static function debug($s, $o = null) {
112-
self::instance()->log(self::DEBUG, $s, $o);
155+
self::instance()->logDebug($s, $o);
156+
}
157+
158+
/**
159+
* Debug message into log.
160+
* @param string $s - the message
161+
* @param mixed $o - an oject to be dumped along with message. An Exception object will cause a stacktrace dump (optional).
162+
*/
163+
public function logDebug($s, $o = null) {
164+
$this->log(self::DEBUG, $s, $o);
113165
}
114166

115167
/**
@@ -118,7 +170,16 @@ public static function debug($s, $o = null) {
118170
* @param mixed $o - an oject to be dumped along with message. An Exception object will cause a stacktrace dump (optional).
119171
*/
120172
public static function info($s, $o = null) {
121-
self::instance()->log(self::INFO, $s, $o);
173+
self::instance()->logInfo($s, $o);
174+
}
175+
176+
/**
177+
* Info message into log.
178+
* @param string $s - the message
179+
* @param mixed $o - an oject to be dumped along with message. An Exception object will cause a stacktrace dump (optional).
180+
*/
181+
public function logInfo($s, $o = null) {
182+
$this->log(self::INFO, $s, $o);
122183
}
123184

124185
/**
@@ -127,7 +188,16 @@ public static function info($s, $o = null) {
127188
* @param mixed $o - an oject to be dumped along with message. An Exception object will cause a stacktrace dump (optional).
128189
*/
129190
public static function warn($s, $o = null) {
130-
self::instance()->log(self::WARN, $s, $o);
191+
self::instance()->logWarn($s, $o);
192+
}
193+
194+
/**
195+
* Warning message into log.
196+
* @param string $s - the message
197+
* @param mixed $o - an oject to be dumped along with message. An Exception object will cause a stacktrace dump (optional).
198+
*/
199+
public function logWarn($s, $o = null) {
200+
$this->log(self::WARN, $s, $o);
131201
}
132202

133203
/**
@@ -136,7 +206,16 @@ public static function warn($s, $o = null) {
136206
* @param mixed $o - an oject to be dumped along with message. An Exception object will cause a stacktrace dump (optional).
137207
*/
138208
public static function error($s, $o = null) {
139-
self::instance()->log(self::ERROR, $s, $o);
209+
self::instance()->logError($s, $o);
210+
}
211+
212+
/**
213+
* Error message into log.
214+
* @param string $s - the message
215+
* @param mixed $o - an oject to be dumped along with message. An Exception object will cause a stacktrace dump (optional).
216+
*/
217+
public function logError($s, $o = null) {
218+
$this->log(self::ERROR, $s, $o);
140219
}
141220

142221
/**
@@ -175,8 +254,16 @@ public static function errorStackTrace($excludeFile = NULL) {
175254
* Set the global log level.
176255
* @param $sev - shall be debug, info, warn, error or none.
177256
*/
178-
public static function setLogLevel($sev) {
179-
self::$logLevel = $sev;
257+
public static function setDefaultLogLevel($sev) {
258+
self::$defaultLogLevel = $sev;
259+
}
260+
261+
/**
262+
* Set the global log entry prefix.
263+
* @param $appName - default prefix for log entries.
264+
*/
265+
public static function setDefaultAppName($appName) {
266+
self::$defaultAppName = $appName;
180267
}
181268

182269
/**
@@ -214,11 +301,11 @@ public static function get() {
214301
* @param string $sev - the log level to check
215302
* @return TRUE when the current loglevel allows logging.
216303
*/
217-
protected static function isLogLevelIncluded($sev) {
304+
protected function isLogLevelIncluded($sev) {
218305
if (self::$logPriorities == null) {
219306
self::$logPriorities = array(self::NONE, self::DEBUG, self::INFO, self::WARN, self::ERROR);
220307
}
221-
$logIndex = array_search(self::$logLevel, self::$logPriorities);
308+
$logIndex = array_search($this->logLevel, self::$logPriorities);
222309
$sevIndex = array_search($sev, self::$logPriorities);
223310
return $logIndex <= $sevIndex;
224311
}

src/TgUtils/FormatUtils.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace TgUtils;
4+
5+
use \TgI18n\I18N;
6+
7+
I18N::addI18nFile(__DIR__ . '/../utils_i18n.php', FALSE);
8+
9+
/**
10+
* Provides some formatting utils.
11+
* @author ralph
12+
*
13+
*/
14+
class FormatUtils {
15+
16+
/**
17+
* Format a price value using localization.
18+
* @param float $value - the value
19+
* @param string $currency - the currency
20+
* @param string $language - the language code (optional, default language of I18N class).
21+
* @param string $spaceChar - the space character to be used between value and currency (optional, default is HTML non-breaking space).
22+
* @return string the formatted price in localized manner.
23+
*/
24+
public static function formatPrice($value, $currency, $language = null, $spaceChar = '&nbsp;') {
25+
return number_format(floatval($value), 2, I18N::_('decimal_point', $language), I18N::_('thousand_sep', $language)).$spaceChar.$currency;
26+
}
27+
28+
/**
29+
* Format a unit by using prefixes (decimal and computer bytes only).
30+
* @param int $size - the size to be formatted
31+
* @param string $unit - the unit string
32+
* @param int $precision - how many digits after decimal point shall be displayed (optional, default is 1)
33+
* @param string $language - the language to be used for number formatting separators (optional, default is NULL)
34+
* @param bool $bytes - TRUE when computer byte counting is used, FALSE when decimal base shall be applied (optional, default is TRUE)
35+
* @return string a formatted string
36+
*/
37+
public static function formatUnit($size, $unit, $precision = 1, $language = NULL, $bytes = TRUE) {
38+
$prefixes = $bytes ? array('K', 'M', 'G', 'T' ) : array('k', 'M', 'G', 'T');
39+
$rc = $unit;
40+
$base = $bytes ? 1024 : 1000;
41+
// Only until GB
42+
if ($size > $base) {
43+
$size = $size/$base;
44+
$rc = $prefixes[0].$unit;
45+
}
46+
if ($size > $base) {
47+
$size = $size/$base;
48+
$rc = $prefixes[1].$unit;
49+
}
50+
if ($size > $base) {
51+
$size = $size/$base;
52+
$rc = $prefixes[2].$unit;
53+
}
54+
if ($size > $base) {
55+
$size = $size/$base;
56+
$rc = $prefixes[3].$unit;
57+
}
58+
$size = $rc != $unit ? number_format($size, $precision, I18N::_('decimal_point', $language), I18N::_('thousand_sep', $language)) : number_format($size, 0, I18N::_('decimal_point', $language), I18N::_('thousand_sep', $language));
59+
return $size.' '.$rc;
60+
}
61+
}
62+

0 commit comments

Comments
 (0)