--- /dev/null
+<?php
+
+namespace App\Services;
+
+use Cubist\Util\Files\Files;
+use Cubist\Util\Zip;
+use Exception;
+use GuzzleHttp\Client;
+use GuzzleHttp\Psr7\Request;
+use GuzzleHttp\Psr7\Utils;
+use SplFileInfo;
+use stdClass;
+
+class WorkshopV2
+{
+
+ /** @var Client */
+ protected $_http;
+
+ /** @var string */
+ protected $_domain = 'https://workshop.fluidbook.com/';
+
+ public function __construct()
+ {
+ $this->_http = new Client(['base_uri' => $this->_domain, 'timeout' => 60000, 'read_timeout' => 60000]);
+ }
+
+ public function login($username, $password)
+ {
+ $response = $this->_request('/', 'post', array('user_email' => $username, 'user_password' => $password));
+ }
+
+ public function installBookIfNeeded($id, $dir, $timestamp = 'auto', $version = 'online')
+ {
+ if ($timestamp === 'auto') {
+ $timestamp = max($this->getMetadata($id)->date, time() - (3600 * 48));
+ }
+
+ $install = false;
+ if (!file_exists($dir) || (!file_exists($dir . '/TIME') && !file_exists($dir . '/_TIME')) || !file_exists($dir . '/index.html')) {
+ $install = true;
+ } else if ($timestamp !== 'skip') {
+ if (file_exists($dir . '/TIME')) {
+ $date = file_get_contents($dir . '/TIME');
+ } else {
+ $date = file_get_contents($dir . '/_TIME');
+ }
+ if ($date < $timestamp) {
+ $install = true;
+ }
+ }
+
+ if ($install) {
+ return $this->installBook($id, $dir, $version);
+ }
+ return false;
+ }
+
+ public function getMetadata($id)
+ {
+ $response = $this->_request('flash/getMetadata?book_id=' . $id);
+ $xml = $this->_getXMLFromResponse($response);
+
+ $res = new stdClass();
+ $res->title = (string)$xml->title;
+ $res->date = intval((string)$xml->date);
+ return $res;
+ }
+
+ public function installBook($id, $dir, $version = 'online', $tries = 3, $beforeInstallCallback = null)
+ {
+ $url = 'ajax/exportbookExe';
+
+ $response = $this->_request($url, 'POST', array('version' => $version, 'book_id' => $id, 'action' => 'download'));
+ $xml = $this->_getXMLFromResponse($response);
+
+ if ($xml !== false && isset($xml->redirection) && !is_null($xml->redirection)) {
+ $this->downloadBook((string)$xml->redirection, $dir, $beforeInstallCallback);
+ return true;
+ } else {
+ if ($tries == 0) {
+ throw new Exception('Unable to download book');
+ }
+ $this->validDownloadBook($id);
+ $this->installBook($id, $dir, $version, $tries - 1, $beforeInstallCallback);
+ return true;
+ }
+ }
+
+ public function validDownloadBook($id)
+ {
+ return $this->_request('ajax/downbook/' . $id . '/html', 'post', array('valide' => '1'));
+ }
+
+ public function downloadBook($uri, $dir, $beforeInstallCallback = null)
+ {
+ set_time_limit(0);
+ $response = $this->_stream($uri);
+ // Unzip
+ $tdir = $dir . '.temp';
+ echo $response->getStreamName();
+ Zip::extract($response->getStreamName(), $tdir);
+ file_put_contents($tdir . '/TIME', time());
+
+ set_time_limit(0);
+ Files::rmdir($dir);
+
+ if (null !== $beforeInstallCallback && is_callable($beforeInstallCallback)) {
+ call_user_func($beforeInstallCallback);
+ }
+ Files::mkdir($dir);
+ echo shell_exec("mv -f \$tdir/* \$dir");
+ if (!file_exists($dir . '/_TIME')) {
+ file_put_contents($dir . '/_TIME', time());
+ }
+ Files::rmdir($tdir);
+ }
+
+ public function createBook($title, $from = null)
+ {
+ $params = ['title' => $title];
+ if (null !== $from) {
+ $params['book'] = $from;
+ }
+ $res = $this->_request('ajax/newBook', 'post', $params)->getBody();
+ preg_match('/\<url\>\/editor\/(\d+)\<\/url\>/i', $res, $matches);
+ return $matches[1];
+ }
+
+ public function uploadPDF($book_id, $file)
+ {
+ if ($file instanceof SplFileInfo) {
+ $spl = $file;
+ } else {
+ $spl = new SplFileInfo($file);
+ }
+ $args = ['append' => $book_id,
+ 'fileName' => $spl->getFilename(),
+ 'fileSize' => $spl->getSize(),
+ 'modificationDate' => $spl->getMTime(),
+ 'creationDate' => $spl->getCTime(),
+ ];
+
+ return $this->_request('flash/uploadDocument', 'post', $args, false, [$spl]);
+ }
+
+ /**
+ *
+ * @param \Psr\Http\Message\ResponseInterface $response
+ * @return \$1|SimpleXMLElement|false|\SimpleXMLElement
+ */
+ protected function _getXMLFromResponse($response)
+ {
+ $body = $response->getBody();
+ return @simplexml_load_string($body);
+ }
+
+ /**
+ * @param $uri
+ * @param string $method
+ * @param array $parameters
+ * @param false $stream
+ * @param array $files
+ * @return \Psr\Http\Message\ResponseInterface|void
+ * @throws \GuzzleHttp\Exception\GuzzleException
+ */
+ protected function _request($uri, $method = 'get', $parameters = array(), $stream = false, $files = array())
+ {
+ try {
+
+ $options = ['stream' => $stream];
+ if (count($files)) {
+ $options['multipart'] = [];
+ foreach ($parameters as $k => $v) {
+ $options['multipart'][] = ['name' => $k, 'content' => $v];
+ }
+ foreach ($files as $file) {
+ if ($file instanceof SplFileInfo) {
+ $spl = $file;
+ } else {
+ $spl = new SplFileInfo($file);
+ }
+ $options['multipart'][] = ['name' => 'file[]',
+ 'contents' => Utils::tryFopen($spl->getPathname(), 'r'),
+ 'filename' => $spl->getFilename()];
+ }
+ } else if ($method === 'post') {
+ $options['form_params'] = $parameters;
+ } else {
+ $options['query'] = $parameters;
+ }
+
+ $request = new Request($method, $this->_domain . ltrim($uri, '/'), $options);
+ return $this->_http->send($request);
+ } catch (Exception $e) {
+ die($e->getMessage());
+ }
+ }
+
+ /**
+ *
+ * @param string $uri
+ * @param string $method
+ * @param array $parameters
+ * @return
+ */
+ protected function _stream($uri, $method = 'get', $parameters = array())
+ {
+ return $this->_request($uri, $method, $parameters, true);
+ }
+
+ protected function _resetClient()
+ {
+
+ }
+
+}