diff --git a/README.md b/README.md index 68a5221..d12970f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Neocities PHP Client Library -Neocities-php is a PHP wrapper of the [Neocities.org](https://neocities.org/) API. +Neocities-php is a PHP wrapper of the [Neocities.org](https://neocities.org/) API. Now with [Jigsaw](https://jigsaw.tighten.co/) integration ## Installation ```sh @@ -77,3 +77,40 @@ $result = $neocities->key(); var_dump($result); ``` + +## Jigsaw Integration + +Neocities-PHP can be integrated with [Tighten's Jigsaw](https://jigsaw.tighten.co/). After installing this packing into your jigsaw project, Register the plugin in `bootstrap.php` +```php +// bootstrap.php +Jigsaw::mixin(new \ReedJones\Neocities\NeocitiesDeployment($container)); +``` + +With this in place, all that is left to do is add your neocities api key your your .env file (if id doesn't exist, create it) +```sh +# .env +NEO_CITIES_API_KEY="YOUR_API_KEY_HERE" +``` + +Now to build & deploy from the command line, run the new `jigsaw deploy` command which accepts the same parameters as the `build` command. +```sh +# Build & deploy your 'local' build +./vendor/bin/jigsaw deploy +``` +```sh +# Build & deploy your 'production' build +./vendor/bin/jigsaw deploy production +``` + +### Jigsaw Programmatic Usage + +After following the above instructions for setting up a neocities deployment with jigsaw, a `deployToNeocities` method is available for programmatic use from bootstrap.php (or elsewhere). An Example: +```php +// Programmatic API Usage +$events->afterBuild(function (Jigsaw $jigsaw) { + if ($jigsaw->getEnvironment() === 'production') { + // Automatic deployment after all production builds + $jigsaw->deployToNeocities(); + } +}); +``` diff --git a/src/Neocities.php b/src/Neocities.php index 2aee913..dd8f943 100644 --- a/src/Neocities.php +++ b/src/Neocities.php @@ -1,246 +1,247 @@ -username = $credentials['username']; - } - - if (isset($credentials['password'])) { - $this->password = $credentials['password']; - } - - if (isset($credentials['apiKey'])) { - $this->apiKey = $credentials['apiKey']; - } - - $validateAuth = $this->ApiAuth(); - - if (isset($options['url'])) { - $this->options = $this->parseUrl($options['url']); - } else { - $this->options = $this->parseUrl('https://neocities.org'); - } - } - - /** - * Lists all files on your site - * - * @return mixed - */ - public function list() - { - return $this->Get('list'); - } - - /** - * Gets info about your site - * - * @return mixed - */ - public function info() - { - return $this->Get('info'); - } - - /** - * Retrieves api key - * - * @return mixed - */ - public function key() - { - return $this->Get('key'); - } - - /** - * Upload files to the server - * - * @param array $files - * - * @return mixed - */ - public function upload($files) - { - foreach ($files as $name => &$place) { - $place = curl_file_create($place); - } - // var_dump($files); die; - return $this->Post('upload', $files); - } - - /** - * Delete files from the server - * - * @param array $files - * - * @return mixed - */ - public function delete($files) - { - foreach ($files as &$file) { - $file = "filenames[]={$file}"; - } - - return $this->Post('delete', implode('&', $files)); - } - - /** - * Retrieves data from api endpoint via GET method - * - * @param string $method - * - * @return mixed $result - */ - private function Get($method) - { - $endpoint = "api/{$method}"; - $options = $this->options; - $url = $options['subdomain'] ? $options['subdomain'] . '.' : ''; - $url .= $options['domain'] . '.' . $options['tld']; - - $ch = curl_init(); - - if (isset($this->apiKey)) { - $neo_api = "{$options['protocall']}://{$url}/{$endpoint}"; - $authorization = "Authorization: Bearer {$this->apiKey}"; - curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json' , $authorization ]); - } else { - $neo_api = "{$options['protocall']}://{$this->ApiAuth()}@{$url}/{$endpoint}"; - } - - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_URL, $neo_api); - $result = curl_exec($ch); - curl_close($ch); - return json_decode($result); - } - - /** - * Sends data to the api endpoint via POST method - * - * @param string $method - * @param mixed $data - * - * @return mixed $result - */ - private function Post($method, $data) - { - $endpoint = "api/{$method}"; - $options = $this->options; - $url = $options['subdomain'] ? $options['subdomain'] . '.' : ''; - $url .= $options['domain'] . '.' . $options['tld']; - - $ch = curl_init(); - if (isset($this->apiKey)) { - // echo 'API'; die; - $neo_api = "{$options['protocall']}://{$url}/{$endpoint}"; - $authorization = "Authorization: Bearer {$this->apiKey}"; - curl_setopt($ch, CURLOPT_HTTPHEADER, [ $authorization ]); - } else { - $neo_api = "{$options['protocall']}://{$this->ApiAuth()}@{$url}/{$endpoint}"; - } - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_URL, $neo_api); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - $result = curl_exec($ch); - curl_close($ch); - return json_decode($result); - } - - /** - * Gets either the api key, or username:password - * depending on what was provided in the class constructor - * - * @return string - */ - private function ApiAuth() - { - if (isset($this->apiKey)) { - return $this->apiKey; - } else if (isset($this->username) && isset($this->password)) { - return implode(':', [$this->username, $this->password]); - } else { - throw new \Exception('No valid credentials provided'); - } - } - - /** - * Parse a URL into usable parts - * - * @param string $url - * - * @return array - */ - private function parseUrl(string $url) - { - $re = '/^(?https?):\/\/((?.+)\.)?(?.+)\.(?[a-zA-Z]{2,})$/m'; - - preg_match($re, $url, $matches); - - return [ - 'protocall' => isset($matches['protocall']) ? $matches['protocall'] : 'http://', - 'subdomain' => $matches['subdomain'], - 'domain' => $matches['domain'], - 'tld' => $matches['tld'], - 'url' => $url - ]; - } -} +username = $credentials['username']; + } + + if (isset($credentials['password'])) { + $this->password = $credentials['password']; + } + + if (isset($credentials['apiKey'])) { + $this->apiKey = $credentials['apiKey']; + } + + $validateAuth = $this->ApiAuth(); + + if (isset($options['url'])) { + $this->options = $this->parseUrl($options['url']); + } else { + $this->options = $this->parseUrl('https://neocities.org'); + } + } + + /** + * Lists all files on your site. + * + * @return mixed + */ + public function list() + { + return $this->Get('list'); + } + + /** + * Gets info about your site. + * + * @return mixed + */ + public function info() + { + return $this->Get('info'); + } + + /** + * Retrieves api key. + * + * @return mixed + */ + public function key() + { + return $this->Get('key'); + } + + /** + * Upload files to the server. + * + * @param array $files + * + * @return mixed + */ + public function upload($files) + { + foreach ($files as $name => &$place) { + $place = curl_file_create($place); + } + // var_dump($files); die; + return $this->Post('upload', $files); + } + + /** + * Delete files from the server. + * + * @param array $files + * + * @return mixed + */ + public function delete($files) + { + foreach ($files as &$file) { + $file = "filenames[]={$file}"; + } + + return $this->Post('delete', implode('&', $files)); + } + + /** + * Retrieves data from api endpoint via GET method. + * + * @param string $method + * + * @return mixed $result + */ + private function Get($method) + { + $endpoint = "api/{$method}"; + $options = $this->options; + $url = $options['subdomain'] ? $options['subdomain'].'.' : ''; + $url .= $options['domain'].'.'.$options['tld']; + + $ch = curl_init(); + + if (isset($this->apiKey)) { + $neo_api = "{$options['protocall']}://{$url}/{$endpoint}"; + $authorization = "Authorization: Bearer {$this->apiKey}"; + curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', $authorization]); + } else { + $neo_api = "{$options['protocall']}://{$this->ApiAuth()}@{$url}/{$endpoint}"; + } + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_URL, $neo_api); + $result = curl_exec($ch); + curl_close($ch); + + return json_decode($result); + } + + /** + * Sends data to the api endpoint via POST method. + * + * @param string $method + * @param mixed $data + * + * @return mixed $result + */ + private function Post($method, $data) + { + $endpoint = "api/{$method}"; + $options = $this->options; + $url = $options['subdomain'] ? $options['subdomain'].'.' : ''; + $url .= $options['domain'].'.'.$options['tld']; + + $ch = curl_init(); + if (isset($this->apiKey)) { + // echo 'API'; die; + $neo_api = "{$options['protocall']}://{$url}/{$endpoint}"; + $authorization = "Authorization: Bearer {$this->apiKey}"; + curl_setopt($ch, CURLOPT_HTTPHEADER, [$authorization]); + } else { + $neo_api = "{$options['protocall']}://{$this->ApiAuth()}@{$url}/{$endpoint}"; + } + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_URL, $neo_api); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + $result = curl_exec($ch); + curl_close($ch); + + return json_decode($result); + } + + /** + * Gets either the api key, or username:password + * depending on what was provided in the class constructor. + * + * @return string + */ + private function ApiAuth() + { + if (isset($this->apiKey)) { + return $this->apiKey; + } elseif (isset($this->username) && isset($this->password)) { + return implode(':', [$this->username, $this->password]); + } else { + throw new \Exception('No credentials provided. API key, or username/password required. Refer to the docs for more information'); + } + } + + /** + * Parse a URL into usable parts. + * + * @param string $url + * + * @return array + */ + private function parseUrl(string $url) + { + $re = '/^(?https?):\/\/((?.+)\.)?(?.+)\.(?[a-zA-Z]{2,})$/m'; + + preg_match($re, $url, $matches); + + return [ + 'protocall' => isset($matches['protocall']) ? $matches['protocall'] : 'http://', + 'subdomain' => $matches['subdomain'], + 'domain' => $matches['domain'], + 'tld' => $matches['tld'], + 'url' => $url, + ]; + } +} diff --git a/src/NeocitiesDeployment.php b/src/NeocitiesDeployment.php new file mode 100644 index 0000000..f2d5a3e --- /dev/null +++ b/src/NeocitiesDeployment.php @@ -0,0 +1,40 @@ +get(Jigsaw::class)->registerCommand(RegisterDeploymentCommand::class); + } + } + + public function deployToNeocities() + { + return function () { + $this->app->singleton(Neocities::class, function ($c) { + return new Neocities(['apiKey' => env('NEO_CITIES_API_KEY')]); + }); + + $buildDir = str_replace(__DIR__, '', $this->getDestinationPath()); + + $files = collect($this->getFilesystem()->allFiles(__DIR__.$buildDir)) + ->flatMap(function ($file) use ($buildDir) { + $file = $file->getRelativePathname(); + + return [$file => ".{$buildDir}/$file"]; + }) + ->toArray(); + + $this->app->get(Neocities::class)->upload($files); + + return $this->app->get(Neocities::class)->info(); + }; + } +} diff --git a/src/RegisterDeploymentCommand.php b/src/RegisterDeploymentCommand.php new file mode 100644 index 0000000..eeb5339 --- /dev/null +++ b/src/RegisterDeploymentCommand.php @@ -0,0 +1,34 @@ +jigsaw = $container->get(Jigsaw::class); + parent::__construct($container); + } + + protected function configure() + { + parent::configure(); + + // Override default name & description + $this->setName('deploy') + ->setDescription('Build & Deploy your site to neocities.'); + } + + protected function fire() + { + parent::fire(); + $env = $this->input->getArgument('env'); + $info = $this->jigsaw->deployToNeocities(); + $this->console->info("Site deployed from {$env} to https://{$info->info->sitename}.neocities.org"); + } +}