Browse Source

Code formatting

main
Cédric Belin 4 months ago
parent
commit
4f46bf110a
20 changed files with 265 additions and 258 deletions
  1. +6
    -3
      .editorconfig
  2. +1
    -1
      .github/workflows/build.yaml
  3. +5
    -5
      .vscode/settings.json
  4. +3
    -3
      doc/index.md
  5. +5
    -5
      doc/installation.md
  6. +23
    -23
      doc/usage.md
  7. +9
    -5
      etc/mkdocs.yaml
  8. +22
    -22
      etc/phpdoc.xml
  9. +2
    -2
      etc/phpstan.neon
  10. +13
    -13
      etc/phpunit.xml
  11. +10
    -10
      example/main.php
  12. +3
    -3
      share/api.http
  13. +86
    -86
      src/Client.php
  14. +19
    -19
      src/ClientException.php
  15. +16
    -16
      src/RequestEvent.php
  16. +18
    -18
      src/ResponseEvent.php
  17. +19
    -19
      test/ClientTest.php
  18. +3
    -3
      tool/clean.ps1
  19. +1
    -1
      tool/doc.ps1
  20. +1
    -1
      tool/upgrade.ps1

+ 6
- 3
.editorconfig View File

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

[*]
charset = utf-8
indent_size = 2
indent_style = space
indent_style = tab
insert_final_newline = true
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
}

+ 3
- 3
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).
@@ -23,7 +23,7 @@ This will give you an identification key allowing access to the [Free Mobile](ht
### Get the library
Install the latest version of **Free Mobile for PHP** with [Composer](https://getcomposer.org):

```shell
``` shell
composer require cedx/free-mobile
```



+ 5
- 5
doc/installation.md View File

@@ -6,7 +6,7 @@ and [Composer](https://getcomposer.org), the PHP package manager, up and running

You can verify if you're already good to go with the following commands:

```shell
``` shell
php --version
# PHP 7.4.5 (cli) (built: Apr 14 2020 16:17:19) ( NTS Visual C++ 2017 x64 )

@@ -15,22 +15,22 @@ 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

### 1. Install it
From a command prompt, run:

```shell
``` shell
composer require cedx/free-mobile
```

### 2. Import it
Now in your [PHP](https://www.php.net) code, you can use:

```php
``` php
<?php
use FreeMobile\{Client, ClientException};
```

+ 23
- 23
doc/usage.md View File

@@ -8,31 +8,31 @@ source: src/Client.php
## SMS notifications
**Free Mobile for PHP** provides the `FreeMobile\Client` class, which allow to send SMS messages to your mobile phone by using the `sendMessage()` method:

```php
``` php
<?php
use FreeMobile\{Client, ClientException};

function main(): void {
try {
$client = new Client('your account identifier', 'your API key');
// For example: new Client('12345678', 'a9BkVohJun4MAf')
try {
$client = new Client("your account identifier", "your API key");
// For example: new Client("12345678", "a9BkVohJun4MAf")

$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;
}
}
```

The `Client->sendMessage()` method throws a `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 `FreeMobile\Client` class is an [EventDispatcher](https://symfony.com/doc/current/components/event_dispatcher.html) that triggers some events during its life cycle.
@@ -40,29 +40,29 @@ The `FreeMobile\Client` class is an [EventDispatcher](https://symfony.com/doc/cu
### The `Client::eventRequest` event
Emitted every time a request is made to the remote service:

```php
``` php
<?php
use FreeMobile\{Client, RequestEvent};

function main(): void {
$client = new Client('your account identifier', 'your API key');
$client->addListener(Client::eventRequest, function(RequestEvent $event) {
echo 'Client request: ', $event->getRequest()->getUri();
});
$client = new Client("your account identifier", "your API key");
$client->addListener(Client::eventRequest, function(RequestEvent $event) {
echo "Client request: ", $event->getRequest()->getUri();
});
}
```

### The `Client::eventResponse` event
Emitted every time a response is received from the remote service:

```php
``` php
<?php
use FreeMobile\{Client, ResponseEvent};

function main(): void {
$client = new Client('your account identifier', 'your API key');
$client->addListener(Client::eventResponse, function(ResponseEvent $event) {
echo 'Server response: ', $event->getResponse()->getStatusCode();
});
$client = new Client("your account identifier", "your API key");
$client->addListener(Client::eventResponse, function(ResponseEvent $event) {
echo "Server response: ", $event->getResponse()->getStatusCode();
});
}
```

+ 9
- 5
etc/mkdocs.yaml View File

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

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

copyright: Copyright &copy; 2016 - 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 PHP</title>
<paths>
<cache>../var/phpdoc</cache>
<output>../doc/api</output>
</paths>
<version number="15.1.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 PHP</title>
<paths>
<cache>../var/phpdoc</cache>
<output>../doc/api</output>
</paths>
<version number="15.1.0">
<api>
<markers>
<marker>TODO</marker>
</markers>
<source dsn="..">
<path>src</path>
</source>
<visibility>protected</visibility>
<visibility>public</visibility>
</api>
</version>
</phpdocumentor>

+ 2
- 2
etc/phpstan.neon View File

@@ -1,3 +1,3 @@
parameters:
level: max
paths: [../src, ../test]
level: max
paths: [../src, ../test]

+ 13
- 13
etc/phpunit.xml View File

@@ -1,18 +1,18 @@
<?xml version="1.0"?>
<phpunit bootstrap="../vendor/autoload.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>

+ 10
- 10
example/main.php View File

@@ -3,16 +3,16 @@ use FreeMobile\{Client, ClientException};

/** Sends an SMS notification. */
function main(): void {
try {
$client = new Client('your account identifier', 'your API key');
// For example: new Client('12345678', 'a9BkVohJun4MAf')
try {
$client = new Client("your account identifier", "your API key");
// For example: new Client("12345678", "a9BkVohJun4MAf")

$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;
}
}

+ 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}}

+ 86
- 86
src/Client.php View File

@@ -8,90 +8,90 @@ use Symfony\Component\HttpClient\{Psr18Client};
/** Sends messages by SMS to a Free Mobile account. */
class Client extends EventDispatcher {

/** @var string An event that is triggered when a request is made to the remote service. */
const eventRequest = RequestEvent::class;
/** @var string An event that is triggered when a response is received from the remote service. */
const eventResponse = ResponseEvent::class;
/** @var UriInterface The URL of the API end point. */
private UriInterface $endPoint;
/** @var Psr18Client The HTTP client. */
private Psr18Client $http;
/** @var string The identification key associated to the account. */
private string $password;
/** @var string The user name associated to the account. */
private string $username;
/**
* Creates a new client.
* @param string $username The user name associated to the account.
* @param string $password The identification key associated to the account.
* @param UriInterface|null $endPoint The URL of the API end point.
*/
function __construct(string $username, string $password, ?UriInterface $endPoint = null) {
assert(mb_strlen($username) > 0);
assert(mb_strlen($password) > 0);
parent::__construct();
$this->http = new Psr18Client;
$this->endPoint = $endPoint ?? $this->http->createUri('https://smsapi.free-mobile.fr/');
$this->password = $password;
$this->username = $username;
}
/**
* Gets the URL of the API end point.
* @return UriInterface The URL of the API end point.
*/
function getEndPoint(): UriInterface {
return $this->endPoint;
}
/**
* Gets the identification key associated to the account.
* @return string The identification key associated to the account.
*/
function getPassword(): string {
return $this->password;
}
/**
* Gets the user name associated to the account.
* @return string The user name associated to the account.
*/
function getUsername(): string {
return $this->username;
}
/**
* 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->getPassword(),
'user' => $this->getUsername()
], '', '&', PHP_QUERY_RFC3986));
try {
$request = $this->http->createRequest('GET', $uri);
$this->dispatch(new RequestEvent($request));
$response = $this->http->sendRequest($request);
$this->dispatch(new ResponseEvent($response, $request));
}
catch (\Throwable $e) {
throw new ClientException($e->getMessage(), $uri, $e);
}
}
/** @var string An event that is triggered when a request is made to the remote service. */
const eventRequest = RequestEvent::class;
/** @var string An event that is triggered when a response is received from the remote service. */
const eventResponse = ResponseEvent::class;
/** @var UriInterface The URL of the API end point. */
private UriInterface $endPoint;
/** @var Psr18Client The HTTP client. */
private Psr18Client $http;
/** @var string The identification key associated to the account. */
private string $password;
/** @var string The user name associated to the account. */
private string $username;
/**
* Creates a new client.
* @param string $username The user name associated to the account.
* @param string $password The identification key associated to the account.
* @param UriInterface|null $endPoint The URL of the API end point.
*/
function __construct(string $username, string $password, ?UriInterface $endPoint = null) {
assert(mb_strlen($username) > 0);
assert(mb_strlen($password) > 0);
parent::__construct();
$this->http = new Psr18Client;
$this->endPoint = $endPoint ?? $this->http->createUri("https://smsapi.free-mobile.fr/");
$this->password = $password;
$this->username = $username;
}
/**
* Gets the URL of the API end point.
* @return UriInterface The URL of the API end point.
*/
function getEndPoint(): UriInterface {
return $this->endPoint;
}
/**
* Gets the identification key associated to the account.
* @return string The identification key associated to the account.
*/
function getPassword(): string {
return $this->password;
}
/**
* Gets the user name associated to the account.
* @return string The user name associated to the account.
*/
function getUsername(): string {
return $this->username;
}
/**
* 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->getPassword(),
"user" => $this->getUsername()
], "", "&", PHP_QUERY_RFC3986));
try {
$request = $this->http->createRequest("GET", $uri);
$this->dispatch(new RequestEvent($request));
$response = $this->http->sendRequest($request);
$this->dispatch(new ResponseEvent($response, $request));
}
catch (\Throwable $e) {
throw new ClientException($e->getMessage(), $uri, $e);
}
}
}

+ 19
- 19
src/ClientException.php View File

@@ -6,25 +6,25 @@ use Psr\Http\Message\{UriInterface};
/** An exception caused by an error in a `Client` request. */
class ClientException extends \RuntimeException {

/** @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($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($message, ?UriInterface $uri = null, ?\Throwable $previous = null) {
parent::__construct($message, 0, $previous);
$this->uri = $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;
}
/**
* 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;
}
}

+ 16
- 16
src/RequestEvent.php View File

@@ -7,22 +7,22 @@ use Symfony\Contracts\EventDispatcher\{Event};
/** Represents the event parameter used for request events. */
class RequestEvent extends Event {

/** @var RequestInterface The related HTTP request. */
private RequestInterface $request;
/** @var RequestInterface The related HTTP request. */
private RequestInterface $request;

/**
* Creates a new request event.
* @param RequestInterface $request The related HTTP request.
*/
function __construct(RequestInterface $request) {
$this->request = $request;
}
/**
* Creates a new request event.
* @param RequestInterface $request The related HTTP request.
*/
function __construct(RequestInterface $request) {
$this->request = $request;
}

/**
* Gets the related HTTP request.
* @return RequestInterface The related HTTP request.
*/
function getRequest(): RequestInterface {
return $this->request;
}
/**
* Gets the related HTTP request.
* @return RequestInterface The related HTTP request.
*/
function getRequest(): RequestInterface {
return $this->request;
}
}

+ 18
- 18
src/ResponseEvent.php View File

@@ -6,24 +6,24 @@ use Psr\Http\Message\{RequestInterface, ResponseInterface};
/** Represents the event parameter used for response events. */
class ResponseEvent extends RequestEvent {

/** @var ResponseInterface The related HTTP response. */
private ResponseInterface $response;
/** @var ResponseInterface The related HTTP response. */
private ResponseInterface $response;

/**
* Creates a new response event.
* @param ResponseInterface $response The related HTTP response.
* @param RequestInterface $request The request that triggered this response.
*/
function __construct(ResponseInterface $response, RequestInterface $request) {
parent::__construct($request);
$this->response = $response;
}
/**
* Creates a new response event.
* @param ResponseInterface $response The related HTTP response.
* @param RequestInterface $request The request that triggered this response.
*/
function __construct(ResponseInterface $response, RequestInterface $request) {
parent::__construct($request);
$this->response = $response;
}

/**
* Gets the related HTTP response.
* @return ResponseInterface The related HTTP response.
*/
function getResponse(): ResponseInterface {
return $this->response;
}
/**
* Gets the related HTTP response.
* @return ResponseInterface The related HTTP response.
*/
function getResponse(): ResponseInterface {
return $this->response;
}
}

+ 19
- 19
test/ClientTest.php View File

@@ -8,26 +8,26 @@ use function PHPUnit\Framework\{assertThat, isInstanceOf, isNull, stringStartsWi
/** @testdox FreeMobile\Client */
class ClientTest extends TestCase {

/** @testdox ->sendMessage() */
function testSendMessage(): void {
// It should throw a `ClientException` if a network error occurred.
try {
(new Client('anonymous', 'secret', new Uri('http://localhost:10000/')))->sendMessage('Hello World!');
Assert::fail('Exception not thrown');
}
/** @testdox ->sendMessage() */
function testSendMessage(): void {
// It should throw a `ClientException` if a network error occurred.
try {
(new Client("anonymous", "secret", new Uri("http://localhost:10000/")))->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((string) getenv('FREEMOBILE_USERNAME'), (string) getenv('FREEMOBILE_PASSWORD'));
$client->addListener(Client::eventRequest, function(RequestEvent $event) {
assertThat((string) $event->getRequest()->getUri(), stringStartsWith('https://smsapi.free-mobile.fr/sendmsg?'));
});
// It should trigger events.
$client = new Client((string) getenv("FREEMOBILE_USERNAME"), (string) getenv("FREEMOBILE_PASSWORD"));
$client->addListener(Client::eventRequest, function(RequestEvent $event) {
assertThat((string) $event->getRequest()->getUri(), stringStartsWith("https://smsapi.free-mobile.fr/sendmsg?"));
});

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

+ 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