From de7b15435172fbfaf09351ed00ced8b487256b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Goetz?= Date: Tue, 26 Jan 2016 12:00:07 +0100 Subject: [PATCH] [Confluence] Add options on the update_threshold, and ability to specify a root_id instead of ancestor_id --- daux.phar | Bin 877516 -> 878823 bytes docs/05_Configuration/Confluence_upload.md | 33 +++++++++++++++++ libs/Format/Confluence/Api.php | 35 ++++++++++++++++-- libs/Format/Confluence/Publisher.php | 39 +++++++++++++++------ 4 files changed, 95 insertions(+), 12 deletions(-) diff --git a/daux.phar b/daux.phar index 06d73438af5069fa580704643ecf48d55cab720b..9f6a55c623becd406528fc5b5c8f3226a7899d7e 100755 GIT binary patch delta 6190 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 BjTZm_ delta 5334 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 BzD@uD diff --git a/docs/05_Configuration/Confluence_upload.md b/docs/05_Configuration/Confluence_upload.md index 269267e..2bbabc3 100644 --- a/docs/05_Configuration/Confluence_upload.md +++ b/docs/05_Configuration/Confluence_upload.md @@ -27,6 +27,10 @@ You can obtain the `ancestor_id` id by editing the page you want to define as a } ``` +You can also provide a `root_id` instead of an `ancestor_id` in this case, you specify the id as the homepage of your documentation. + +You can use that when you're uploading your documentation to the root of a Confluence Space or if your page already exists. + ## Prefix Because confluence can't have two pages with the same name in a space, I recommend you define a prefix for your pages. @@ -35,3 +39,32 @@ Because confluence can't have two pages with the same name in a space, I recomme "confluence": { "prefix": "[DAUX]" } } ``` + +## Update threshold +To make the upload quicker, we try to determine if a page changed or not, first with a strict comparison and if it's not completely identical, we compute the difference. + +```json +{ + "confluence": { "update_threshold": 1 } +} +``` + +If you set `update_threshold` to 1, it will upload only if the page has more than 1% difference with the previous one. + +By default the threshold is 2%. + +Setting the value to `0` disables the feature altogether. + + +## Delete old pages +When a page is renamed, there is no way to tell it was renamed, so when uploading to Confluence, the page will be uploaded and the old page will stay here. + +By default, it will inform you that some pages aren't needed anymore and you can delete them by hand. + +```json +{ + "confluence": { "delete": true } +} +``` + +By setting `delete` to `true` (or running `daux.phar` with the `--delete` flag) you tell the generator that it can safely delete the pages. diff --git a/libs/Format/Confluence/Api.php b/libs/Format/Confluence/Api.php index 403fa04..fa434a7 100644 --- a/libs/Format/Confluence/Api.php +++ b/libs/Format/Confluence/Api.php @@ -76,6 +76,31 @@ class Api return new BadResponseException($message, $request, $response, $e->getPrevious()); } + public function getPage($id) + { + $url = "content/$id?expand=ancestors,version,body.storage"; + + try { + $result = $this->getClient()->get($url)->json(); + } catch (BadResponseException $e) { + throw $this->handleError($e); + } + + $ancestor_id = null; + if (array_key_exists('ancestors', $result) && count($result['ancestors'])) { + $ancestor_page = end($result['ancestors']); // We need the direct parent + $ancestor_id = $ancestor_page['id']; + } + + return [ + "id" => $result['id'], + "ancestor_id" => $ancestor_id, + "title" => $result['title'], + "version" => $result['version']['number'], + "content" => $result['body']['storage']['value'], + ]; + } + /** * Get a list of pages * @@ -137,11 +162,14 @@ class Api $body = [ 'type' => 'page', 'space' => ['key' => $this->space], - 'ancestors' => [['type' => 'page', 'id' => $parent_id]], 'title' => $title, 'body' => ['storage' => ['value' => $content, 'representation' => 'storage']] ]; + if ($parent_id) { + $body['ancestors'] = [['type' => 'page', 'id' => $parent_id]]; + } + try { $response = $this->getClient()->post('content', ['json' => $body])->json(); } catch (BadResponseException $e) { @@ -163,12 +191,15 @@ class Api $body = [ 'type' => 'page', 'space' => ['key' => $this->space], - 'ancestors' => [['type' => 'page', 'id' => $parent_id]], 'version' => ['number' => $newVersion, "minorEdit" => true], 'title' => $title, 'body' => ['storage' => ['value' => $content, 'representation' => 'storage']] ]; + if ($parent_id) { + $body['ancestors'] = [['type' => 'page', 'id' => $parent_id]]; + } + try { $this->getClient()->put("content/$page_id", ['json' => $body])->json(); } catch (BadResponseException $e) { diff --git a/libs/Format/Confluence/Publisher.php b/libs/Format/Confluence/Publisher.php index 4796823..c5e79df 100644 --- a/libs/Format/Confluence/Publisher.php +++ b/libs/Format/Confluence/Publisher.php @@ -54,16 +54,26 @@ class Publisher public function publish(array $tree) { + echo "Finding Root Page...\n"; - $pages = $this->client->getList($this->confluence['ancestor_id']); - $published = null; - foreach ($pages as $page) { - if ($page['title'] == $tree['title']) { - $published = $page; - break; + if (array_key_exists('ancestor_id', $this->confluence)) { + $pages = $this->client->getList($this->confluence['ancestor_id']); + $published = null; + foreach ($pages as $page) { + if ($page['title'] == $tree['title']) { + $published = $page; + break; + } } + } elseif (array_key_exists('root_id', $this->confluence)) { + $published = $this->client->getPage($this->confluence['root_id']); + $this->confluence['ancestor_id'] = $published['ancestor_id']; + } else { + throw new \RuntimeException("You must at least specify a `root_id` or `ancestor_id` in your confluence configuration."); } + + $this->run( "Getting already published pages...", function() use (&$published) { @@ -104,6 +114,7 @@ class Publisher { echo "- " . $this->niceTitle($entry['file']->getUrl()) . "\n"; $published['version'] = 1; + $published['title'] = $entry['title']; $published['id'] = $this->client->createPage($parent_id, $entry['title'], "The content will come very soon !"); return $published; @@ -113,6 +124,7 @@ class Publisher { echo "- " . $entry['title'] . "\n"; $published['version'] = 1; + $published['title'] = $entry['title']; $published['id'] = $this->client->createPage($parent_id, $entry['title'], ""); return $published; @@ -220,13 +232,20 @@ class Publisher return false; } - similar_text($trimmed_local, $trimmed_distant, $percent); - // I consider that if the files are 98% identical you // don't need to update. This will work for false positives. // But sadly will miss if it's just a typo update - if ($percent >= 98) { - return false; + // This is configurable with `update_threshold` + $threshold = 98; + if (array_key_exists('update_threshold', $this->confluence)) { + $threshold = 100 - $this->confluence['update_threshold']; + } + + if ($threshold < 100) { + similar_text($trimmed_local, $trimmed_distant, $percent); + if ($percent > $threshold) { + return false; + } } //DEBUG