Browse Source

Code formatting

main
Cédric Belin 2 months ago
parent
commit
6a37c004a9
22 changed files with 424 additions and 415 deletions
  1. +8
    -3
      .editorconfig
  2. +1
    -1
      .github/workflows/build.yaml
  3. +5
    -5
      .vscode/settings.json
  4. +53
    -53
      composer.json
  5. +2
    -2
      doc/index.md
  6. +5
    -5
      doc/installation.md
  7. +49
    -49
      doc/usage.md
  8. +9
    -5
      etc/mkdocs.yaml
  9. +22
    -22
      etc/phpdoc.xml
  10. +4
    -4
      etc/phpstan.neon
  11. +13
    -13
      etc/phpunit.xml
  12. +22
    -22
      example/main.php
  13. +3
    -3
      share/api.http
  14. +82
    -82
      src/Client.php
  15. +26
    -26
      src/ClientException.php
  16. +37
    -37
      src/LogTarget.php
  17. +26
    -26
      test/ClientTest.php
  18. +47
    -47
      test/LogTargetTest.php
  19. +5
    -5
      test/index.php
  20. +3
    -3
      tool/clean.ps1
  21. +1
    -1
      tool/doc.ps1
  22. +1
    -1
      tool/upgrade.ps1

+ 8
- 3
.editorconfig View File

@@ -3,11 +3,16 @@ root = true

[*]
charset = utf-8
indent_size = 2
indent_style = space
indent_style = tab
insert_final_newline = true
max_line_length = 200
quote_type = double
tab_width = 2
trim_trailing_whitespace = true

[*.md]
indent_size = 4
trim_trailing_whitespace = false

[*.{yaml,yml}]
indent_size = 2
indent_style = space

+ 1
- 1
.github/workflows/build.yaml View File

@@ -3,7 +3,7 @@ on:
pull_request:
push:
schedule:
- cron: '0 0 1 * *'
- cron: "0 0 1 * *"
jobs:
test:
runs-on: ubuntu-latest


+ 5
- 5
.vscode/settings.json View File

@@ -1,7 +1,7 @@
{
"editor.insertSpaces": true,
"editor.tabSize": 2,
"files.encoding": "utf8",
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true
"editor.insertSpaces": false,
"editor.tabSize": 2,
"files.encoding": "utf8",
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true
}

+ 53
- 53
composer.json View File

@@ -1,55 +1,55 @@
{
"description": "Send SMS messages to your Free Mobile device, for the Yii Framework. A simple and free way to monitor your applications using a Free Mobile account.",
"homepage": "https://docs.belin.io/yii2-free-mobile",
"license": "MIT",
"name": "cedx/yii2-free-mobile",
"type": "yii2-extension",
"version": "11.2.0",
"authors": [
{"email": "cedric@belin.io", "homepage": "https://belin.io", "name": "Cédric Belin"}
],
"autoload": {
"psr-4": {"yii\\freemobile\\": "src/"}
},
"autoload-dev": {
"psr-4": {"yii\\freemobile\\": "test/"}
},
"config": {
"fxp-asset": {"enabled": false},
"optimize-autoloader": true
},
"funding": [
{"type": "patreon", "url": "https://www.patreon.com/cedx"}
],
"keywords": [
"client",
"free",
"logging",
"mobile",
"sms",
"yii2"
],
"repositories": [
{"type": "composer", "url": "https://asset-packagist.org"}
],
"require": {
"php": ">=7.4.0",
"ext-mbstring": "*",
"nyholm/psr7": "^1.2.1",
"yiisoft/yii2": "^2.0.35",
"yiisoft/yii2-httpclient": "^2.0.12"
},
"require-dev": {
"cedx/coveralls": "^13.0.0",
"phpstan/phpstan": "^0.12.25",
"phpunit/phpunit": "^9.1.4"
},
"scripts": {
"coverage": "coveralls var/coverage.xml",
"test": "phpunit --configuration=etc/phpunit.xml"
},
"support": {
"docs": "https://api.belin.io/yii2-free-mobile",
"issues": "https://git.belin.io/cedx/yii2-free-mobile/issues"
}
"description": "Send SMS messages to your Free Mobile device, for the Yii Framework. A simple and free way to monitor your applications using a Free Mobile account.",
"homepage": "https://docs.belin.io/yii2-free-mobile",
"license": "MIT",
"name": "cedx/yii2-free-mobile",
"type": "yii2-extension",
"version": "11.2.0",
"authors": [
{"email": "cedric@belin.io", "homepage": "https://belin.io", "name": "Cédric Belin"}
],
"autoload": {
"psr-4": {"yii\\freemobile\\": "src/"}
},
"autoload-dev": {
"psr-4": {"yii\\freemobile\\": "test/"}
},
"config": {
"fxp-asset": {"enabled": false},
"optimize-autoloader": true
},
"funding": [
{"type": "patreon", "url": "https://www.patreon.com/cedx"}
],
"keywords": [
"client",
"free",
"logging",
"mobile",
"sms",
"yii2"
],
"repositories": [
{"type": "composer", "url": "https://asset-packagist.org"}
],
"require": {
"php": ">=7.4.0",
"ext-mbstring": "*",
"nyholm/psr7": "^1.2.1",
"yiisoft/yii2": "^2.0.35",
"yiisoft/yii2-httpclient": "^2.0.12"
},
"require-dev": {
"cedx/coveralls": "^13.0.0",
"phpstan/phpstan": "^0.12.25",
"phpunit/phpunit": "^9.1.4"
},
"scripts": {
"coverage": "coveralls var/coverage.xml",
"test": "phpunit --configuration=etc/phpunit.xml"
},
"support": {
"docs": "https://api.belin.io/yii2-free-mobile",
"issues": "https://git.belin.io/cedx/yii2-free-mobile/issues"
}
}

+ 2
- 2
doc/index.md View File

@@ -11,8 +11,8 @@ For example, you can configure a control panel or a network-attached storage to
## Quick start

!!! warning
SMS notifications require an API key. If you are not already registered,
[sign up for a Free Mobile account](https://mobile.free.fr/subscribe).
SMS notifications require an API key. If you are not already registered,
[sign up for a Free Mobile account](https://mobile.free.fr/subscribe).

### Get an API key
You first need to enable the **SMS notifications** in [your subscriber account](https://mobile.free.fr/moncompte).


+ 5
- 5
doc/installation.md View File

@@ -15,8 +15,8 @@ composer --version
```

!!! info
If you plan to play with the package sources, you will also need the latest versions of
[PowerShell](https://docs.microsoft.com/en-us/powershell) and [Material for MkDocs](https://squidfunk.github.io/mkdocs-material).
If you plan to play with the package sources, you will also need the latest versions of
[PowerShell](https://docs.microsoft.com/en-us/powershell) and [Material for MkDocs](https://squidfunk.github.io/mkdocs-material).

## Installing with Composer package manager

@@ -33,8 +33,8 @@ Now in your [PHP](https://www.php.net) code, you can use:
```php
<?php
use yii\freemobile\{
Client,
ClientException,
LogTarget
Client,
ClientException,
LogTarget
};
```

+ 49
- 49
doc/usage.md View File

@@ -8,29 +8,29 @@
use yii\freemobile\{Client, ClientException};

function main(): void {
try {
$config = [
'username' => 'your account identifier', // e.g. "12345678"
'password' => 'your API key' // e.g. "a9BkVohJun4MA"
];
$client = new Client($config);
$client->sendMessage('Hello World!');
echo 'The message was sent successfully';
}
catch (Throwable $e) {
echo 'An error occurred: ', $e->getMessage(), PHP_EOL;
if ($e instanceof ClientException) echo 'From: ', $e->getUri(), PHP_EOL;
}
try {
$config = [
"username" => "your account identifier", // e.g. "12345678"
"password" => "your API key" // e.g. "a9BkVohJun4MA"
];
$client = new Client($config);
$client->sendMessage("Hello World!");
echo "The message was sent successfully";
}
catch (Throwable $e) {
echo "An error occurred: ", $e->getMessage(), PHP_EOL;
if ($e instanceof ClientException) echo "From: ", $e->getUri(), PHP_EOL;
}
}
```

The `Client->sendMessage()` method throws a `yii\freemobile\ClientException` if any error occurred while sending the message.

!!! warning
The text of the messages will be automatically truncated to **160** characters:
you can't send multipart messages using this library.
The text of the messages will be automatically truncated to **160** characters:
you can't send multipart messages using this library.

## Client events
The `yii\freemobile\Client` class triggers some [events](https://www.yiiframework.com/doc/guide/2.0/en/concept-events) during its life cycle.
@@ -44,10 +44,10 @@ use yii\freemobile\{Client};
use yii\httpclient\{RequestEvent};

function main(): void {
$client = new Client(['username' => 'your account identifier', 'password' => 'your API key']);
$client->on(Client::eventRequest, function(RequestEvent $event) {
echo 'Client request: ', $event->request->url;
});
$client = new Client(["username" => "your account identifier", "password" => "your API key"]);
$client->on(Client::eventRequest, function(RequestEvent $event) {
echo "Client request: ", $event->request->url;
});
}
```

@@ -60,10 +60,10 @@ use yii\freemobile\{Client};
use yii\httpclient\{RequestEvent};

function main(): void {
$client = new Client(['username' => 'your account identifier', 'password' => 'your API key']);
$client->on(Client::eventResponse, function(RequestEvent $event) {
echo 'Server response: ', $event->response->statusCode;
});
$client = new Client(["username" => "your account identifier", "password" => "your API key"]);
$client->on(Client::eventResponse, function(RequestEvent $event) {
echo "Server response: ", $event->response->statusCode;
});
}
```

@@ -74,13 +74,13 @@ In your [application configuration](https://www.yiiframework.com/doc/guide/2.0/e

```php
<?php return [
'components' => [
'freemobile' => [
'class' => 'yii\freemobile\Client',
'username' => 'your account identifier', // e.g. "12345678"
'password' => 'your API key' // e.g. "a9BkVohJun4MA"
]
]
"components" => [
"freemobile" => [
"class" => "yii\\freemobile\\Client",
"username" => "your account identifier", // e.g. "12345678"
"password" => "your API key" // e.g. "a9BkVohJun4MA"
]
]
];
```

@@ -88,8 +88,8 @@ Once the `freemobile` component is initialized with your credentials, you can us

```php
<?php
$client = \Yii::$app->get('freemobile');
$client->sendMessage('Hello World!');
$client = \Yii::$app->get("freemobile");
$client->sendMessage("Hello World!");
```

### Logging
@@ -97,24 +97,24 @@ In your [application configuration](https://www.yiiframework.com/doc/guide/2.0/e

```php
<?php return [
'bootstrap' => ['log'],
'components' => [
'log' => [
'targets' => [
[
'class' => 'yii\freemobile\LogTarget',
'client' => 'freemobile',
'levels' => ['error']
]
]
]
]
"bootstrap" => ["log"],
"components" => [
"log" => [
"targets" => [
[
"class" => "yii\\freemobile\\LogTarget",
"client" => "freemobile",
"levels" => ["error"]
]
]
]
]
];
```

The optional `LogTarget->client` property accepts a `yii\freemobile\Client` instance or the application component ID of a Free Mobile client. It defaults to the `"freemobile"` string.

!!! tip
As text of the log messages is truncated to **160** characters,
you should not change the default value of the `LogTarget->exportInterval`
and `LogTarget->logVars` properties.
As text of the log messages is truncated to **160** characters,
you should not change the default value of the `LogTarget->exportInterval`
and `LogTarget->logVars` properties.

+ 9
- 5
etc/mkdocs.yaml View File

@@ -10,19 +10,23 @@ site_dir: ../www

repo_name: git.belin.io
repo_url: https://git.belin.io/cedx/yii2-free-mobile
edit_uri: ''
edit_uri: ""

copyright: Copyright &copy; 2014 - 2020 Cédric Belin
extra:
social:
- icon: fontawesome/solid/globe
link: 'https://belin.io'
link: "https://belin.io"
name: Belin.io
- icon: fontawesome/brands/github
link: 'https://github.com/cedx'
link: "https://github.com/cedx"
name: GitHub
- icon: fontawesome/brands/twitter
link: 'https://twitter.com/cedxbelin'
link: "https://twitter.com/cedxbelin"
name: Twitter
- icon: fontawesome/brands/linkedin
link: 'https://linkedin.com/in/cedxbelin'
link: "https://linkedin.com/in/cedxbelin"
name: LinkedIn

markdown_extensions:
- admonition


+ 22
- 22
etc/phpdoc.xml View File

@@ -1,25 +1,25 @@
<?xml version="1.0"?>
<phpdocumentor
configVersion="3"
xmlns="http://www.phpdoc.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://docs.phpdoc.org/latest/phpdoc.xsd">
<title>Free Mobile for Yii</title>
<paths>
<cache>../var/phpdoc</cache>
<output>../doc/api</output>
</paths>
<version number="11.2.0">
<api>
<markers>
<marker>TODO</marker>
</markers>
<source dsn="..">
<path>src</path>
</source>
<visibility>protected</visibility>
<visibility>public</visibility>
</api>
</version>
configVersion="3"
xmlns="http://www.phpdoc.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://docs.phpdoc.org/latest/phpdoc.xsd">
<title>Free Mobile for Yii</title>
<paths>
<cache>../var/phpdoc</cache>
<output>../doc/api</output>
</paths>
<version number="11.2.0">
<api>
<markers>
<marker>TODO</marker>
</markers>
<source dsn="..">
<path>src</path>
</source>
<visibility>protected</visibility>
<visibility>public</visibility>
</api>
</version>
</phpdocumentor>

+ 4
- 4
etc/phpstan.neon View File

@@ -1,5 +1,5 @@
parameters:
autoload_files: [../vendor/yiisoft/yii2/Yii.php]
level: max
paths: [../src, ../test]
treatPhpDocTypesAsCertain: false
autoload_files: [../vendor/yiisoft/yii2/Yii.php]
level: max
paths: [../src, ../test]
treatPhpDocTypesAsCertain: false

+ 13
- 13
etc/phpunit.xml View File

@@ -1,18 +1,18 @@
<?xml version="1.0"?>
<phpunit bootstrap="../test/index.php" cacheResult="false" testdox="true">
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">../src</directory>
</whitelist>
</filter>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">../src</directory>
</whitelist>
</filter>

<logging>
<log type="coverage-clover" target="../var/coverage.xml"/>
</logging>
<logging>
<log type="coverage-clover" target="../var/coverage.xml"/>
</logging>

<testsuites>
<testsuite name="all">
<directory suffix="Test.php">../test</directory>
</testsuite>
</testsuites>
<testsuites>
<testsuite name="all">
<directory suffix="Test.php">../test</directory>
</testsuite>
</testsuites>
</phpunit>

+ 22
- 22
example/main.php View File

@@ -3,33 +3,33 @@ use yii\freemobile\{Client, ClientException, LogTarget};

/** Sends an SMS notification to a Free Mobile account. */
function sendNotification(): void {
try {
$client = new Client([
'username' => 'your account identifier', // e.g. "12345678"
'password' => 'your API key' // e.g. "a9BkVohJun4MA"
]);
try {
$client = new Client([
"username" => "your account identifier", // e.g. "12345678"
"password" => "your API key" // e.g. "a9BkVohJun4MA"
]);

$client->sendMessage('Hello World!');
echo 'The message was sent successfully';
}
$client->sendMessage("Hello World!");
echo "The message was sent successfully";
}

catch (Throwable $e) {
echo 'An error occurred: ', $e->getMessage(), PHP_EOL;
if ($e instanceof ClientException) echo 'From: ', $e->getUri(), PHP_EOL;
}
catch (Throwable $e) {
echo "An error occurred: ", $e->getMessage(), PHP_EOL;
if ($e instanceof ClientException) echo "From: ", $e->getUri(), PHP_EOL;
}
}

/** Logs a message by using an SMS notification. */
function logMessage(): void {
Yii::$app->log->targets[] = new LogTarget([
'categories' => ['app*'],
'levels' => ['error'],
'client' => [
'class' => Client::class,
'username' => 'your account identifier', // e.g. "12345678"
'password' => 'your API key' // e.g. "a9BkVohJun4MA"
]
]);
Yii::$app->log->targets[] = new LogTarget([
"categories" => ["app*"],
"levels" => ["error"],
"client" => [
"class" => Client::class,
"username" => "your account identifier", // e.g. "12345678"
"password" => "your API key" // e.g. "a9BkVohJun4MA"
]
]);

Yii::error('An error occurred.');
Yii::error("An error occurred.");
}

+ 3
- 3
share/api.http View File

@@ -6,6 +6,6 @@

// Sends a SMS message to the underlying account.
GET {{baseUrl}}/sendmsg
?msg=Bonjour%20C%C3%A9dric%20!
&pass={{password}}
&user={{username}}
?msg=Bonjour%20C%C3%A9dric%20!
&pass={{password}}
&user={{username}}

+ 82
- 82
src/Client.php View File

@@ -13,86 +13,86 @@ use yii\web\{HttpException};
*/
class Client extends Component {

/** @var string An event that is triggered when a request is made to the remote service. */
const eventRequest = 'request';
/** @var string An event that is triggered when a response is received from the remote service. */
const eventResponse = 'response';
/** @var string The identification key associated to the account. */
public string $password = '';
/** @var string The user name associated to the account. */
public string $username = '';
/** @var UriInterface The URL of the API end point. */
private UriInterface $endPoint;
/** @var HttpClient The underlying HTTP client. */
private HttpClient $http;
/**
* Creates a new client.
* @param array<string, mixed> $config Name-value pairs that will be used to initialize the object properties.
*/
function __construct(array $config = []) {
$this->endPoint = new Uri('https://smsapi.free-mobile.fr/');
$this->http = new HttpClient(['transport' => extension_loaded('curl') ? CurlTransport::class : StreamTransport::class]);
$this->http->on(HttpClient::EVENT_BEFORE_SEND, fn($event) => $this->trigger(static::eventRequest, $event));
$this->http->on(HttpClient::EVENT_AFTER_SEND, fn($event) => $this->trigger(static::eventResponse, $event));
parent::__construct($config);
}
/**
* Gets the URL of the API end point.
* @return UriInterface The URL of the API end point.
*/
function getEndPoint(): UriInterface {
return $this->endPoint;
}
/**
* Initializes this object.
* @throws InvalidConfigException The account credentials are invalid.
*/
function init(): void {
parent::init();
if (!mb_strlen($this->username) || !mb_strlen($this->password)) throw new InvalidConfigException('The account credentials are invalid.');
}
/**
* Sends a SMS message to the underlying account.
* @param string $text The text of the message to send.
* @throws ClientException An error occurred while sending the message.
*/
function sendMessage(string $text): void {
assert(mb_strlen($text) > 0);
$endPoint = $this->getEndPoint();
$uri = $endPoint->withPath("{$endPoint->getPath()}sendmsg")->withQuery(http_build_query([
'msg' => mb_substr(trim($text), 0, 160),
'pass' => $this->password,
'user' => $this->username
], '', '&', PHP_QUERY_RFC3986));
try {
$response = $this->http->get((string) $uri)->send();
if (!$response->getIsOk()) throw new HttpException((int) $response->getStatusCode(), $response->getContent());
}
catch (\Throwable $e) {
throw new ClientException($e->getMessage(), $uri, $e);
}
}
/**
* Sets the URL of the API end point.
* @param string|UriInterface $value The new URL.
* @return $this This instance.
*/
function setEndPoint($value): self {
assert(is_string($value) || $value instanceof UriInterface);
$this->endPoint = (is_string($value) ? new Uri($value) : $value)->withUserInfo('');
return $this;
}
/** @var string An event that is triggered when a request is made to the remote service. */
const eventRequest = "request";
/** @var string An event that is triggered when a response is received from the remote service. */
const eventResponse = "response";
/** @var string The identification key associated to the account. */
public string $password = "";
/** @var string The user name associated to the account. */
public string $username = "";
/** @var UriInterface The URL of the API end point. */
private UriInterface $endPoint;
/** @var HttpClient The underlying HTTP client. */
private HttpClient $http;
/**
* Creates a new client.
* @param array<string, mixed> $config Name-value pairs that will be used to initialize the object properties.
*/
function __construct(array $config = []) {
$this->endPoint = new Uri("https://smsapi.free-mobile.fr/");
$this->http = new HttpClient(["transport" => extension_loaded("curl") ? CurlTransport::class : StreamTransport::class]);
$this->http->on(HttpClient::EVENT_BEFORE_SEND, fn($event) => $this->trigger(static::eventRequest, $event));
$this->http->on(HttpClient::EVENT_AFTER_SEND, fn($event) => $this->trigger(static::eventResponse, $event));
parent::__construct($config);
}
/**
* Gets the URL of the API end point.
* @return UriInterface The URL of the API end point.
*/
function getEndPoint(): UriInterface {
return $this->endPoint;
}
/**
* Initializes this object.
* @throws InvalidConfigException The account credentials are invalid.
*/
function init(): void {
parent::init();
if (!mb_strlen($this->username) || !mb_strlen($this->password)) throw new InvalidConfigException("The account credentials are invalid.");
}
/**
* Sends a SMS message to the underlying account.
* @param string $text The text of the message to send.
* @throws ClientException An error occurred while sending the message.
*/
function sendMessage(string $text): void {
assert(mb_strlen($text) > 0);
$endPoint = $this->getEndPoint();
$uri = $endPoint->withPath("{$endPoint->getPath()}sendmsg")->withQuery(http_build_query([
"msg" => mb_substr(trim($text), 0, 160),
"pass" => $this->password,
"user" => $this->username
], "", "&", PHP_QUERY_RFC3986));
try {
$response = $this->http->get((string) $uri)->send();
if (!$response->getIsOk()) throw new HttpException((int) $response->getStatusCode(), $response->getContent());
}
catch (\Throwable $e) {
throw new ClientException($e->getMessage(), $uri, $e);
}
}
/**
* Sets the URL of the API end point.
* @param string|UriInterface $value The new URL.
* @return $this This instance.
*/
function setEndPoint($value): self {
assert(is_string($value) || $value instanceof UriInterface);
$this->endPoint = (is_string($value) ? new Uri($value) : $value)->withUserInfo("");
return $this;
}
}

+ 26
- 26
src/ClientException.php View File

@@ -7,33 +7,33 @@ use yii\base\{Exception};
/** An exception caused by an error in a `Client` request. */
class ClientException extends Exception {

/** @var UriInterface|null The URL of the HTTP request or response that failed. */
private ?UriInterface $uri;
/** @var UriInterface|null The URL of the HTTP request or response that failed. */
private ?UriInterface $uri;

/**
* Creates a new client exception.
* @param string $message A message describing the error.
* @param UriInterface|null $uri The URL of the HTTP request or response that failed.
* @param \Throwable|null $previous The previous exception used for the exception chaining.
*/
function __construct(string $message, ?UriInterface $uri = null, ?\Throwable $previous = null) {
parent::__construct($message, 0, $previous);
$this->uri = $uri;
}
/**
* Creates a new client exception.
* @param string $message A message describing the error.
* @param UriInterface|null $uri The URL of the HTTP request or response that failed.
* @param \Throwable|null $previous The previous exception used for the exception chaining.
*/
function __construct(string $message, ?UriInterface $uri = null, ?\Throwable $previous = null) {
parent::__construct($message, 0, $previous);
$this->uri = $uri;
}

/**
* Gets the user-friendly name of this exception.
* @return string The user-friendly name of this exception.
*/
function getName(): string {
return 'Free Mobile Client Exception';
}
/**
* Gets the user-friendly name of this exception.
* @return string The user-friendly name of this exception.
*/
function getName(): string {
return "Free Mobile Client Exception";
}

/**
* Gets the URL of the HTTP request or response that failed.
* @return UriInterface|null The URL of the HTTP request or response that failed.
*/
function getUri(): ?UriInterface {
return $this->uri;
}
/**
* Gets the URL of the HTTP request or response that failed.
* @return UriInterface|null The URL of the HTTP request or response that failed.
*/
function getUri(): ?UriInterface {
return $this->uri;
}
}

+ 37
- 37
src/LogTarget.php View File

@@ -8,45 +8,45 @@ use yii\log\{Target};
/** Sends the log messages by SMS to a Free Mobile account. */
class LogTarget extends Target {

/** @var string|array<string, mixed>|Client The Free Mobile client or the application component ID of the Free Mobile client. */
public $client = 'freemobile';
/** @var string|array<string, mixed>|Client The Free Mobile client or the application component ID of the Free Mobile client. */
public $client = "freemobile";

/**
* Creates a new log target.
* @param array<string, mixed> $config Name-value pairs that will be used to initialize the object properties.
*/
function __construct(array $config = []) {
$this->exportInterval = 1;
$this->logVars = [];
parent::__construct($config);
}
/**
* Creates a new log target.
* @param array<string, mixed> $config Name-value pairs that will be used to initialize the object properties.
*/
function __construct(array $config = []) {
$this->exportInterval = 1;
$this->logVars = [];
parent::__construct($config);
}

/** Exports log messages to a specific destination. */
function export(): void {
/** @var Client $client */
$client = $this->client;
$client->sendMessage(implode("\n", array_map([$this, 'formatMessage'], $this->messages)));
}
/** Exports log messages to a specific destination. */
function export(): void {
/** @var Client $client */
$client = $this->client;
$client->sendMessage(implode("\n", array_map([$this, "formatMessage"], $this->messages)));
}

/**
* Formats a log message for display as a string.
* @param array<int, mixed> $message The log message to be formatted.
* @return string The formatted message.
*/
function formatMessage($message): string {
assert(is_array($message) && count($message) >= 3);
[$text,, $category] = $message;
if (!is_string($text)) $text = $text instanceof \Throwable ? (string) $text : VarDumper::export($text);
return "$category: $text";
}
/**
* Formats a log message for display as a string.
* @param array<int, mixed> $message The log message to be formatted.
* @return string The formatted message.
*/
function formatMessage($message): string {
assert(is_array($message) && count($message) >= 3);
[$text,, $category] = $message;
if (!is_string($text)) $text = $text instanceof \Throwable ? (string) $text : VarDumper::export($text);
return "$category: $text";
}

/** Initializes this object. */
function init(): void {
parent::init();
if (!$this->client instanceof Client) {
/** @var Client $client */
$client = Instance::ensure($this->client, Client::class);
$this->client = $client;
}
}
/** Initializes this object. */
function init(): void {
parent::init();
if (!$this->client instanceof Client) {
/** @var Client $client */
$client = Instance::ensure($this->client, Client::class);
$this->client = $client;
}
}
}

+ 26
- 26
test/ClientTest.php View File

@@ -9,34 +9,34 @@ use function PHPUnit\Framework\{assertThat, isInstanceOf, stringStartsWith};
/** @testdox yii\freemobile\Client */
class ClientTest extends TestCase {

/** @testdox ->init() */
function testInit(): void {
// It should throw an exception if the username or password is empty.
$this->expectException(InvalidConfigException::class);
new Client;
}
/** @testdox ->init() */
function testInit(): void {
// It should throw an exception if the username or password is empty.
$this->expectException(InvalidConfigException::class);
new Client;
}

/** @testdox ->sendMessage() */
function testSendMessage(): void {
// It should throw a `ClientException` if a network error occurred.
try {
$config = ['username' => 'anonymous', 'password' => 'secret', 'endPoint' => 'http://localhost:10000/'];
(new Client($config))->sendMessage('Hello World!');
Assert::fail('Exception not thrown');
}
/** @testdox ->sendMessage() */
function testSendMessage(): void {
// It should throw a `ClientException` if a network error occurred.
try {
$config = ["username" => "anonymous", "password" => "secret", "endPoint" => "http://localhost:10000/"];
(new Client($config))->sendMessage("Hello World!");
Assert::fail("Exception not thrown");
}

catch (\Throwable $e) {
assertThat($e, isInstanceOf(ClientException::class));
}
catch (\Throwable $e) {
assertThat($e, isInstanceOf(ClientException::class));
}

// It should trigger events.
$client = new Client(['username' => getenv('FREEMOBILE_USERNAME'), 'password' => getenv('FREEMOBILE_PASSWORD')]);
$client->on(Client::eventRequest, function(RequestEvent $event) {
assertThat($event->request->getFullUrl(), stringStartsWith('https://smsapi.free-mobile.fr/sendmsg?'));
});
// It should trigger events.
$client = new Client(["username" => getenv("FREEMOBILE_USERNAME"), "password" => getenv("FREEMOBILE_PASSWORD")]);
$client->on(Client::eventRequest, function(RequestEvent $event) {
assertThat($event->request->getFullUrl(), stringStartsWith("https://smsapi.free-mobile.fr/sendmsg?"));
});

// It should send SMS messages if credentials are valid.
try { $client->sendMessage('Bonjour Cédric, à partir du Yii Framework !'); }
catch (\Throwable $e) { Assert::fail($e->getMessage()); }
}
// It should send SMS messages if credentials are valid.
try { $client->sendMessage("Bonjour Cédric, à partir du Yii Framework !"); }
catch (\Throwable $e) { Assert::fail($e->getMessage()); }
}
}

+ 47
- 47
test/LogTargetTest.php View File

@@ -9,51 +9,51 @@ use function PHPUnit\Framework\{assertThat, equalTo, identicalTo, isInstanceOf,
/** @testdox yii\freemobile\LogTarget */
class LogTargetTest extends TestCase {

/** @testdox ->formatMessage() */
function testFormatMessage(): void {
// It should return a formatted message including the log level and category.
$message = ['Hello World!', Logger::LEVEL_ERROR, 'tests', time()];
assertThat((new LogTarget)->formatMessage($message), equalTo('tests: Hello World!'));
}
/** @testdox ->init() */
function testInit(): void {
// It should throw an exception if the client is unavailable.
try {
\Yii::$app->set('freemobile', null);
new LogTarget;
Assert::fail('Exception not thrown');
}
catch (\Throwable $e) {
assertThat($e, isInstanceOf(InvalidConfigException::class));
}
// It should not throw an exception if the client is available.
try {
\Yii::$app->set('freemobile', new Client(['username' => 'anonymous', 'password' => 'secret']));
new LogTarget;
}
catch (\Throwable $e) {
Assert::fail($e->getMessage());
}
// It should allow a customized client component ID.
\Yii::$app->set('freemobileTest', [
'class' => Client::class,
'username' => 'anonymous',
'password' => 'secret'
]);
assertThat((new LogTarget(['client' => 'freemobileTest']))->client, logicalAnd(
isInstanceOf(Client::class),
identicalTo(\Yii::$app->get('freemobileTest'))
));
}
/** @before This method is called before each test. */
protected function setUp(): void {
\Yii::$app->set('freemobile', new Client(['username' => 'anonymous', 'password' => 'secret']));
}
/** @testdox ->formatMessage() */
function testFormatMessage(): void {
// It should return a formatted message including the log level and category.
$message = ["Hello World!", Logger::LEVEL_ERROR, "tests", time()];
assertThat((new LogTarget)->formatMessage($message), equalTo("tests: Hello World!"));
}
/** @testdox ->init() */
function testInit(): void {
// It should throw an exception if the client is unavailable.
try {
\Yii::$app->set("freemobile", null);
new LogTarget;
Assert::fail("Exception not thrown");
}
catch (\Throwable $e) {
assertThat($e, isInstanceOf(InvalidConfigException::class));
}
// It should not throw an exception if the client is available.
try {
\Yii::$app->set("freemobile", new Client(["username" => "anonymous", "password" => "secret"]));
new LogTarget;
}
catch (\Throwable $e) {
Assert::fail($e->getMessage());
}
// It should allow a customized client component ID.
\Yii::$app->set("freemobileTest", [
"class" => Client::class,
"username" => "anonymous",
"password" => "secret"
]);
assertThat((new LogTarget(["client" => "freemobileTest"]))->client, logicalAnd(
isInstanceOf(Client::class),
identicalTo(\Yii::$app->get("freemobileTest"))
));
}
/** @before This method is called before each test. */
protected function setUp(): void {
\Yii::$app->set("freemobile", new Client(["username" => "anonymous", "password" => "secret"]));
}
}

+ 5
- 5
test/index.php View File

@@ -2,15 +2,15 @@
use yii\console\{Application};

// Set the environment.
define('YII_DEBUG', true);
define('YII_ENV', 'test');
define("YII_DEBUG", true);
define("YII_ENV", "test");

// Load the class library.
$rootPath = (new SplFileInfo(__DIR__))->getPath();
require_once "$rootPath/vendor/autoload.php";
require_once "$rootPath/vendor/yiisoft/yii2/Yii.php";
Yii::setAlias('@root', $rootPath);
Yii::setAlias('@yii/freemobile', "$rootPath/src");
Yii::setAlias("@root", $rootPath);
Yii::setAlias("@yii/freemobile", "$rootPath/src");

// Start the application.
new Application(['id' => 'yii2-free-mobile', 'basePath' => '@root/src']);
new Application(["id" => "yii2-free-mobile", "basePath" => "@root/src"]);

+ 3
- 3
tool/clean.ps1 View File

@@ -2,10 +2,10 @@
Set-StrictMode -Version Latest
Set-Location (Split-Path $PSScriptRoot)

foreach ($item in 'build', 'doc/api', 'www') {
if (Test-Path $item) { Remove-Item $item -Recurse }
foreach ($item in "build", "doc/api", "www") {
if (Test-Path $item) { Remove-Item $item -Recurse }
}

foreach ($item in Get-ChildItem var -Exclude .gitkeep) {
Remove-Item $item -Recurse
Remove-Item $item -Recurse
}

+ 1
- 1
tool/doc.ps1 View File

@@ -2,7 +2,7 @@
Set-StrictMode -Version Latest
Set-Location (Split-Path $PSScriptRoot)

$phpdoc = $IsWindows ? 'php "C:/Program Files/PHP/share/phpDocumentor.phar"' : 'phpdoc';
$phpdoc = $IsWindows ? 'php "C:/Program Files/PHP/share/phpDocumentor.phar"' : "phpdoc";
Invoke-Expression "$phpdoc --config=etc/phpdoc.xml"

if (-not (Test-Path doc/api/images)) { New-Item doc/api/images -ItemType Directory | Out-Null }


+ 1
- 1
tool/upgrade.ps1 View File

@@ -6,5 +6,5 @@ git reset --hard
git fetch --all --prune
git pull --rebase

$composer = $IsWindows ? 'php "C:/Program Files/PHP/share/composer.phar"' : 'composer'
$composer = $IsWindows ? 'php "C:/Program Files/PHP/share/composer.phar"' : "composer"
Invoke-Expression "$composer update --no-interaction"

Loading…
Cancel
Save