Implement version command and better help
This commit is contained in:
71
bin/acme
71
bin/acme
@@ -5,15 +5,19 @@ use Auryn\Injector;
|
|||||||
use Kelunik\AcmeClient\AcmeFactory;
|
use Kelunik\AcmeClient\AcmeFactory;
|
||||||
use League\CLImate\CLImate;
|
use League\CLImate\CLImate;
|
||||||
|
|
||||||
|
$logo = <<<LOGO
|
||||||
|
____ __________ ___ ___
|
||||||
|
/ __ `/ ___/ __ `__ \/ _ \
|
||||||
|
/ /_/ / /__/ / / / / / __/
|
||||||
|
\__,_/\___/_/ /_/ /_/\___/
|
||||||
|
|
||||||
|
LOGO;
|
||||||
|
|
||||||
if (!file_exists(__DIR__ . "/../vendor/autoload.php")) {
|
if (!file_exists(__DIR__ . "/../vendor/autoload.php")) {
|
||||||
|
echo $logo;
|
||||||
echo <<<HELP
|
echo <<<HELP
|
||||||
|
|
||||||
____ __________ ___ ___
|
You need to install the composer dependencies.
|
||||||
/ __ `/ ___/ __ `__ \/ _ \
|
|
||||||
/ /_/ / /__/ / / / / / __/
|
|
||||||
\__,_/\___/_/ /_/ /_/\___/
|
|
||||||
|
|
||||||
You need to install the composer dependencies.
|
|
||||||
|
|
||||||
composer install --no-dev
|
composer install --no-dev
|
||||||
|
|
||||||
@@ -23,14 +27,10 @@ HELP;
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!function_exists("openssl_pkey_get_private")) {
|
if (!function_exists("openssl_pkey_get_private")) {
|
||||||
|
echo $logo;
|
||||||
echo <<<HELP
|
echo <<<HELP
|
||||||
|
|
||||||
____ __________ ___ ___
|
You need to enable OpenSSL in your php.ini
|
||||||
/ __ `/ ___/ __ `__ \/ _ \
|
|
||||||
/ /_/ / /__/ / / / / / __/
|
|
||||||
\__,_/\___/_/ /_/ /_/\___/
|
|
||||||
|
|
||||||
You need to enable OpenSSL in your php.ini
|
|
||||||
|
|
||||||
|
|
||||||
HELP;
|
HELP;
|
||||||
@@ -40,54 +40,55 @@ HELP;
|
|||||||
require __DIR__ . "/../vendor/autoload.php";
|
require __DIR__ . "/../vendor/autoload.php";
|
||||||
|
|
||||||
$commands = [
|
$commands = [
|
||||||
"setup",
|
"setup" => "Setup and register account.",
|
||||||
"issue",
|
"issue" => "Issue a new certificate.",
|
||||||
"check",
|
"check" => "Check if a certificate is still valid long enough.",
|
||||||
"revoke",
|
"revoke" => "Revoke a certificate.",
|
||||||
|
"version" => "Print version information.",
|
||||||
];
|
];
|
||||||
|
|
||||||
$binary = \Kelunik\AcmeClient\getBinary();
|
$binary = \Kelunik\AcmeClient\getBinary();
|
||||||
|
|
||||||
$help = implode("\n ", array_map(function ($command) use ($binary) {
|
$help = implode(PHP_EOL, array_map(function ($command) use ($commands) {
|
||||||
return "{$binary} {$command}";
|
$help = " <green>{$command}</green>\n";
|
||||||
}, $commands));
|
$help .= " └─ {$commands[$command]}\n";
|
||||||
|
return $help;
|
||||||
|
}, array_keys($commands)));
|
||||||
|
|
||||||
$help = <<<EOT
|
$help = <<<EOT
|
||||||
|
|
||||||
____ __________ ___ ___
|
<yellow>Usage:</yellow>
|
||||||
/ __ `/ ___/ __ `__ \/ _ \
|
bin/acme [command] [--args]
|
||||||
/ /_/ / /__/ / / / / / __/
|
|
||||||
\__,_/\___/_/ /_/ /_/\___/
|
|
||||||
|
|
||||||
Usage: bin/acme command --args
|
<yellow>Options:</yellow>
|
||||||
|
<green>-h, --help</green>
|
||||||
Available Commands:
|
└─ Print this help message.
|
||||||
{$help}
|
|
||||||
|
|
||||||
Get more help by appending --help to specific commands.
|
|
||||||
|
|
||||||
|
<yellow>Available commands:</yellow>
|
||||||
|
{$help}
|
||||||
|
Get more help by appending <yellow>--help</yellow> to specific commands.
|
||||||
|
|
||||||
EOT;
|
EOT;
|
||||||
|
|
||||||
$climate = new CLImate;
|
$climate = new CLImate;
|
||||||
|
|
||||||
if (!in_array(PHP_SAPI, ["cli", "phpdbg"], true)) {
|
if (!in_array(PHP_SAPI, ["cli", "phpdbg"], true)) {
|
||||||
$climate->error("Please run this script via CLI!");
|
$climate->error("Please run this script on the command line!");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($argv) === 1 || in_array($argv[1], ["h", "-h", "help", "--help"], true)) {
|
if (count($argv) === 1 || in_array($argv[1], ["h", "-h", "help", "--help"], true)) {
|
||||||
$climate->out($help);
|
$climate->out($logo . $help);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in_array($argv[1], $commands)) {
|
if (!in_array($argv[1], array_keys($commands))) {
|
||||||
$climate->br()->error(" Unknown command '{$argv[1]}'. Use --help for a list of available commands.");
|
$climate->error("Unknown command '{$argv[1]}'. Use --help for a list of available commands.");
|
||||||
|
|
||||||
$suggestion = \Kelunik\AcmeClient\suggestCommand($argv[1], $commands);
|
$suggestion = \Kelunik\AcmeClient\suggestCommand($argv[1], array_keys($commands));
|
||||||
|
|
||||||
if ($suggestion) {
|
if ($suggestion) {
|
||||||
$climate->br()->out(" Did you mean '$suggestion'?");
|
$climate->br()->out(" Did you mean '$suggestion'?");
|
||||||
}
|
}
|
||||||
|
|
||||||
$climate->br();
|
$climate->br();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "kelunik/acme-client",
|
"name": "kelunik/acme-client",
|
||||||
"description": "Standalone PHP ACME client.",
|
"description": "Let's Encrypt / ACME client written in PHP for the CLI.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"ACME",
|
"ACME",
|
||||||
"letsencrypt",
|
"letsencrypt",
|
||||||
@@ -24,7 +24,8 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^5",
|
"phpunit/phpunit": "^5",
|
||||||
"fabpot/php-cs-fixer": "^1.9",
|
"fabpot/php-cs-fixer": "^1.9",
|
||||||
"macfja/phar-builder": "dev-master#a2db582eab26ef7b15144c013408749a79fae361"
|
"macfja/phar-builder": "dev-master#97bfa5ffb2bb8beb26db2d5575e852dd10593ac3",
|
||||||
|
"league/event": "^2.1"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"authors": [
|
"authors": [
|
||||||
@@ -48,8 +49,19 @@
|
|||||||
"compression": "GZip",
|
"compression": "GZip",
|
||||||
"name": "acme-client.phar",
|
"name": "acme-client.phar",
|
||||||
"output-dir": "build",
|
"output-dir": "build",
|
||||||
"include": ["src", "vendor/kelunik/acme/res", "vendor/amphp/socket/var"],
|
"include": ["info", "src", "vendor/kelunik/acme/res", "vendor/amphp/socket/var"],
|
||||||
"entry-point": "bin/acme"
|
"entry-point": "bin/acme",
|
||||||
|
"events": {
|
||||||
|
"build.before": [
|
||||||
|
"mkdir -p info",
|
||||||
|
"git describe --tags > info/build.version",
|
||||||
|
"php -r 'echo time();' > info/build.time"
|
||||||
|
],
|
||||||
|
"build.after": [
|
||||||
|
"rm -rf info",
|
||||||
|
"chmod +x build/acme-client.phar"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
97
composer.lock
generated
97
composer.lock
generated
@@ -4,8 +4,8 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "3bfc6d13e53f6be6788859cbdd68b52a",
|
"hash": "e1091f4600ce5c211e5c11f89718d7cf",
|
||||||
"content-hash": "62b8fb8281fc8a7b9925c115301f4707",
|
"content-hash": "55e9166fdb7dfbdbda7ef9144e494cdd",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "amphp/amp",
|
"name": "amphp/amp",
|
||||||
@@ -172,16 +172,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "amphp/dns",
|
"name": "amphp/dns",
|
||||||
"version": "v0.8.9",
|
"version": "v0.8.10",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/amphp/dns.git",
|
"url": "https://github.com/amphp/dns.git",
|
||||||
"reference": "78cda5692a80ec0a5b50ee7616d93426961836ec"
|
"reference": "9f12b2264f74e0cbad67565308f9e106fb6a5bec"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/amphp/dns/zipball/78cda5692a80ec0a5b50ee7616d93426961836ec",
|
"url": "https://api.github.com/repos/amphp/dns/zipball/9f12b2264f74e0cbad67565308f9e106fb6a5bec",
|
||||||
"reference": "78cda5692a80ec0a5b50ee7616d93426961836ec",
|
"reference": "9f12b2264f74e0cbad67565308f9e106fb6a5bec",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -236,7 +236,7 @@
|
|||||||
"dns",
|
"dns",
|
||||||
"resolve"
|
"resolve"
|
||||||
],
|
],
|
||||||
"time": "2016-03-24 19:17:04"
|
"time": "2016-03-26 20:35:44"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "amphp/file",
|
"name": "amphp/file",
|
||||||
@@ -1210,18 +1210,68 @@
|
|||||||
"description": "A tool to automatically fix PHP code style",
|
"description": "A tool to automatically fix PHP code style",
|
||||||
"time": "2016-02-26 07:37:29"
|
"time": "2016-02-26 07:37:29"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "league/event",
|
||||||
|
"version": "2.1.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/thephpleague/event.git",
|
||||||
|
"reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/thephpleague/event/zipball/e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd",
|
||||||
|
"reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.4.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"henrikbjorn/phpspec-code-coverage": "~1.0.1",
|
||||||
|
"phpspec/phpspec": "~2.0.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.2-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"League\\Event\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Frank de Jonge",
|
||||||
|
"email": "info@frenky.net"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Event package",
|
||||||
|
"keywords": [
|
||||||
|
"emitter",
|
||||||
|
"event",
|
||||||
|
"listener"
|
||||||
|
],
|
||||||
|
"time": "2015-05-21 12:24:47"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "macfja/phar-builder",
|
"name": "macfja/phar-builder",
|
||||||
"version": "dev-master",
|
"version": "dev-master",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/MacFJA/PharBuilder.git",
|
"url": "https://github.com/MacFJA/PharBuilder.git",
|
||||||
"reference": "a2db582eab26ef7b15144c013408749a79fae361"
|
"reference": "97bfa5ffb2bb8beb26db2d5575e852dd10593ac3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/MacFJA/PharBuilder/zipball/9396c639ca105f4c07649fbc15200297e8981764",
|
"url": "https://api.github.com/repos/MacFJA/PharBuilder/zipball/8a2d96e9497418729d00df1e86a1778f8a9f3268",
|
||||||
"reference": "a2db582eab26ef7b15144c013408749a79fae361",
|
"reference": "97bfa5ffb2bb8beb26db2d5575e852dd10593ac3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1230,6 +1280,11 @@
|
|||||||
"symfony/console": "~2.6",
|
"symfony/console": "~2.6",
|
||||||
"webignition/readable-duration": "~0"
|
"webignition/readable-duration": "~0"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpmd/phpmd": "^2.4",
|
||||||
|
"sebastian/phpcpd": "^2.0",
|
||||||
|
"squizlabs/php_codesniffer": "^2.5"
|
||||||
|
},
|
||||||
"bin": [
|
"bin": [
|
||||||
"bin/phar-builder",
|
"bin/phar-builder",
|
||||||
"bin/phar-builder.php"
|
"bin/phar-builder.php"
|
||||||
@@ -1261,7 +1316,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "CLI tool for create phar of your composer based project",
|
"description": "CLI tool for create phar of your composer based project",
|
||||||
"time": "2016-03-24 00:08:01"
|
"time": "2016-03-27 12:42:09"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "macfja/symfony-console-filechooser",
|
"name": "macfja/symfony-console-filechooser",
|
||||||
@@ -2346,16 +2401,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v2.8.3",
|
"version": "v2.8.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
"reference": "56cc5caf051189720b8de974e4746090aaa10d44"
|
"reference": "9a5aef5fc0d4eff86853d44202b02be8d5a20154"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/console/zipball/56cc5caf051189720b8de974e4746090aaa10d44",
|
"url": "https://api.github.com/repos/symfony/console/zipball/9a5aef5fc0d4eff86853d44202b02be8d5a20154",
|
||||||
"reference": "56cc5caf051189720b8de974e4746090aaa10d44",
|
"reference": "9a5aef5fc0d4eff86853d44202b02be8d5a20154",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2402,7 +2457,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Console Component",
|
"description": "Symfony Console Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2016-02-28 16:20:50"
|
"time": "2016-03-17 09:19:04"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher",
|
"name": "symfony/event-dispatcher",
|
||||||
@@ -2515,16 +2570,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/finder",
|
"name": "symfony/finder",
|
||||||
"version": "v2.8.3",
|
"version": "v2.8.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/finder.git",
|
"url": "https://github.com/symfony/finder.git",
|
||||||
"reference": "877bb4b16ea573cc8c024e9590888fcf7eb7e0f7"
|
"reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/finder/zipball/877bb4b16ea573cc8c024e9590888fcf7eb7e0f7",
|
"url": "https://api.github.com/repos/symfony/finder/zipball/ca24cf2cd4e3826f571e0067e535758e73807aa1",
|
||||||
"reference": "877bb4b16ea573cc8c024e9590888fcf7eb7e0f7",
|
"reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2560,7 +2615,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Finder Component",
|
"description": "Symfony Finder Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2016-02-22 16:12:45"
|
"time": "2016-03-10 10:53:53"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-mbstring",
|
"name": "symfony/polyfill-mbstring",
|
||||||
|
|||||||
76
src/Commands/Version.php
Normal file
76
src/Commands/Version.php
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kelunik\AcmeClient\Commands;
|
||||||
|
|
||||||
|
use League\CLImate\Argument\Manager;
|
||||||
|
use League\CLImate\CLImate;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
class Version implements Command {
|
||||||
|
private $climate;
|
||||||
|
|
||||||
|
public function __construct(CLImate $climate) {
|
||||||
|
$this->climate = $climate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(Manager $args) {
|
||||||
|
$version = $this->getVersion();
|
||||||
|
|
||||||
|
$buildTime = $this->readFileOr("info/build.time", time());
|
||||||
|
$buildDate = date('M jS Y H:i:s T', (int) trim($buildTime));
|
||||||
|
|
||||||
|
$package = json_decode($this->readFileOr("composer.json", new RuntimeException("No composer.json found.")));
|
||||||
|
|
||||||
|
$this->climate->out("┌ <green>kelunik/acme-client</green> @ <yellow>{$version}</yellow> (built: {$buildDate})");
|
||||||
|
$this->climate->out(($args->defined("deps") ? "│" : "└") . " " . $this->getDescription($package));
|
||||||
|
|
||||||
|
if ($args->defined("deps")) {
|
||||||
|
$lockFile = json_decode($this->readFileOr("composer.lock", new RuntimeException("No composer.lock found.")));
|
||||||
|
$packages = $lockFile->packages;
|
||||||
|
|
||||||
|
for ($i = 0; $i < count($packages); $i++) {
|
||||||
|
$link = $i === count($packages) - 1 ? "└──" : "├──";
|
||||||
|
$this->climate->out("{$link} <green>{$packages[$i]->name}</green> @ <yellow>{$packages[$i]->version}</yellow>");
|
||||||
|
|
||||||
|
$link = $i === count($packages) - 1 ? " " : "│ ";
|
||||||
|
$this->climate->out("{$link} " . $this->getDescription($packages[$i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDescription($package) {
|
||||||
|
return \Kelunik\AcmeClient\ellipsis(isset($package->description) ? $package->description : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getVersion() {
|
||||||
|
if (file_exists(__DIR__ . "/../../.git")) {
|
||||||
|
$version = `git describe --tags`;
|
||||||
|
} else {
|
||||||
|
$version = $this->readFileOr("info/build.version", "-unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
return substr(trim($version), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function readFileOr($file, $default = "") {
|
||||||
|
if (file_exists(__DIR__ . "/../../" . $file)) {
|
||||||
|
return file_get_contents(__DIR__ . "/../../" . $file);
|
||||||
|
} else {
|
||||||
|
if ($default instanceof \Exception || $default instanceof \Throwable) {
|
||||||
|
throw $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getDefinition() {
|
||||||
|
return [
|
||||||
|
"deps" => [
|
||||||
|
"longPrefix" => "deps",
|
||||||
|
"description" => "Show also the bundled dependency versions.",
|
||||||
|
"noValue" => true,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -218,4 +218,26 @@ function getBinary() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $binary;
|
return $binary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cuts a text to a certain length and appends an ellipsis if necessary.
|
||||||
|
*
|
||||||
|
* @param string $text text to shorten
|
||||||
|
* @param int $max maximum length
|
||||||
|
* @param string $append appendix when too long
|
||||||
|
* @return string shortened string
|
||||||
|
*/
|
||||||
|
function ellipsis($text, $max = 70, $append = "…") {
|
||||||
|
if (strlen($text) <= $max) {
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
$out = substr($text, 0, $max);
|
||||||
|
|
||||||
|
if (strpos($text, " ") === false) {
|
||||||
|
return $out . $append;
|
||||||
|
}
|
||||||
|
|
||||||
|
return preg_replace("/\\w+$/", "", $out) . $append;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user