Skip to content

Commit

Permalink
Add separate renderers for GitChangelog
Browse files Browse the repository at this point in the history
- Refactored filename of GitChangelog.php
- Renderer interface added.
- Markdown renderer moved from GitChangelog to its own class.
- Html interface added.
  • Loading branch information
DigiLive committed Oct 28, 2020
1 parent f8ec9f7 commit 2df97ee
Show file tree
Hide file tree
Showing 4 changed files with 379 additions and 139 deletions.
172 changes: 33 additions & 139 deletions src/GitChangeLog.php → src/GitChangelog.php
Expand Up @@ -77,69 +77,19 @@
*/
class GitChangelog
{
/**
* @var string Format of tag strings. {tag} is replaced by the tags found in the git log, {date} is replaced by the
* corresponding tag date.
*/
public $formatTag = "## {tag} ({date})\n\n";
/**
* @var string Format of hashes. {hashes} is replaced by the concatenated commit hashes.
*/
public $formatHashes = "({hashes})";
/**
* @var string Format of subjects. {subject} is replaced by commit subjects, {hashes} is replaced by the formatted
* commit hashes.
*/
public $formatSubject = "* {subject} {hashes}\n";
/**
* @var string Path to a base (changelog) file. The generated changelog can be prepend this file.
*/
public $baseFile;
/**
* @var string Format of a single commit hash. {hash} is replaced by the commit hash.
*/
public $formatHash = '{hash}';
/**
* @var string Path to local git repository. Leave null for repository at current folder.
*/
public $gitPath;
/**
* @var string Value of the oldest tag to include into the generated changelog.
* @see GitChangelog::setFromTag()
*/
protected $fromTag;
/**
* @var string Value of the newest tag to include into the generated changelog.
* @see GitChangelog::setToTag()
*/
protected $toTag = 'HEAD';
/**
* @var array Contains the tags which exist in the git repository.
* @see GitChangelog::fetchTags();
*/
protected $gitTags;
/**
* @var string The generated changelog.
* @see GitChangelog::build()
*/
protected $changelog;
/**
* @var string[] Contains the labels to filter the commit subjects. All subjects which do not start with any of
* these labels will not be listed. To disable this filtering, remove all labels from this variable.
*/
protected $labels = [
// 'Add', // Create a capability e.g. feature, test, dependency.
// 'Cut', // Remove a capability e.g. feature, test, dependency.
// 'Fix', // Fix an issue e.g. bug, typo, accident, misstatement.
// 'Bump', // Increase the version of something e.g. dependency.
// 'Make', // Change the build process, or tooling, or infra.
// 'Start', // Begin doing something; e.g. create a feature flag.
// 'Stop', // End doing something; e.g. remove a feature flag.
// 'Refactor', // A code change that MUST be just a refactoring.
// 'Reformat', // Refactor of formatting, e.g. omit whitespace.
// 'Optimize', // Refactor of performance, e.g. speed up code.
// 'Document', // Refactor of documentation, e.g. help files.
];
/**
* @var array Contains the (processed) information which is fetched from the git repository.
*/
Expand All @@ -161,7 +111,7 @@ class GitChangelog
* @see https://git-scm.com/docs/git-for-each-ref
*/
protected $options = [
'logHeader' => "# Changelog\n\n",
'logHeader' => 'Changelog',
'headSubject' => 'Upcoming changes',
'nextTagDate' => 'Undetermined',
'noChangesMessage' => 'No changes.',
Expand All @@ -171,6 +121,38 @@ class GitChangelog
'tagOrderDesc' => true,
'commitOrder' => 'ASC',
];
/**
* @var string Value of the oldest tag to include into the generated changelog.
* @see GitChangelog::setFromTag()
*/
private $fromTag;
/**
* @var string Value of the newest tag to include into the generated changelog.
* @see GitChangelog::setToTag()
*/
private $toTag = 'HEAD';
/**
* @var array Contains the tags which exist in the git repository.
* @see GitChangelog::fetchTags();
*/
private $gitTags;
/**
* @var string[] Contains the labels to filter the commit subjects. All subjects which do not start with any of
* these labels will not be listed. To disable this filtering, remove all labels from this variable.
*/
private $labels = [
// 'Add', // Create a capability e.g. feature, test, dependency.
// 'Cut', // Remove a capability e.g. feature, test, dependency.
// 'Fix', // Fix an issue e.g. bug, typo, accident, misstatement.
// 'Bump', // Increase the version of something e.g. dependency.
// 'Make', // Change the build process, or tooling, or infra.
// 'Start', // Begin doing something; e.g. create a feature flag.
// 'Stop', // End doing something; e.g. remove a feature flag.
// 'Refactor', // A code change that MUST be just a refactoring.
// 'Reformat', // Refactor of formatting, e.g. omit whitespace.
// 'Optimize', // Refactor of performance, e.g. speed up code.
// 'Document', // Refactor of documentation, e.g. help files.
];

/**
* GitChangelog constructor.
Expand Down Expand Up @@ -223,66 +205,6 @@ public function fetchTags($force = false): array
return $this->gitTags;
}


/**
* Generate the changelog.
*
* The generated changelog will be stored into a class property.
*
* @throws Exception When the defined From- or To-tag doesn't exist in the git repository.
* @see GitChangelog::changelog
*/
public function build(): void
{
$logContent = $this->options['logHeader'];
$commitData = $this->fetchCommitData();

if (!$commitData) {
$logContent .= $this->options['noChangesMessage'];
$this->changelog = $logContent . "\n";

return;
}

if (!$this->options['tagOrderDesc']) {
$commitData = array_reverse($commitData);
}

// Build changelog.
foreach ($commitData as $tag => &$data) {
// Add tag header and date.
$tagData = [$tag, $data['date']];
if ($tag == 'HEAD') {
$tagData = [$this->options['headSubject'], $this->options['nextTagDate']];
}

$logContent .= str_replace(['{tag}', '{date}'], $tagData, $this->formatTag);

// No subjects present for this tag.
if (!$data['subjects']) {
$subject = $this->options['noChangesMessage'];
$logContent .= str_replace(['{subject}', '{hashes}'], [$subject, ''], $this->formatSubject);
$logContent .= "\n";
continue;
}

// Sort commit subjects.
Utilities::natSort($data['subjects'], $this->options['commitOrder']);

// Add commit subjects.
foreach ($data['subjects'] as $subjectKey => &$subject) {
$logContent .= str_replace(
['{subject}', '{hashes}'],
[$subject, $this->formatHashes($data['hashes'][$subjectKey])],
$this->formatSubject
);
}
$logContent .= "\n";
}

$this->changelog = trim($logContent) . "\n";
}

/**
* Fetch the commit data from the git repository.
*
Expand Down Expand Up @@ -395,34 +317,6 @@ private function processCommitData(): void
}
}

/**
* Format the hashes of a commit subject into a string.
*
* Each hash is formatted as defined by property formatHash.
* After formatting, all hashes are concatenated to a single line, comma separated.
* Finally this line is formatted as defined by property formatHashes.
*
* @param array $hashes Hashes to format
*
* @return string Formatted hash string.
* @see GitChangelog::$formatHash
* @see GitChangelog::$formatHashes
*/
protected function formatHashes(array $hashes): string
{
if (!$this->options['addHashes']) {
return '';
}

foreach ($hashes as &$hash) {
$hash = str_replace('{hash}', $hash, $this->formatHash);
}
unset($hash);
$hashes = implode(', ', $hashes);

return str_replace('{hashes}', $hashes, $this->formatHashes);
}

/**
* Save the generated changelog to a file.
*
Expand Down
131 changes: 131 additions & 0 deletions src/Renderers/Html.php
@@ -0,0 +1,131 @@
<?php

/*
* BSD 3-Clause License
*
* Copyright (c) 2020, Ferry Cools (DigiLive)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

namespace DigiLive\GitChangelog\Renderers;

use DigiLive\GitChangelog\GitChangelog;
use DigiLive\GitChangelog\Utilities;
use Exception;

/**
* Class Html
*
* Renderer for GitChangelog.
* The rendered changelog is formatted in markdown.
*
* @package DigiLive\GitChangelog\Renderers
*/
class Html extends GitChangelog implements RendererInterface
{
/**
* @var string Format of a single commit hash. {hash} is replaced by the commit hash.
*/
public $formatHash = '{hash}';

/**
* Generate the changelog.
*
* The generated changelog will be stored into a class property.
*
* @throws Exception When the defined From- or To-tag doesn't exist in the git repository.
*/
public function build(): void
{
$logContent = "<h1>{$this->options['logHeader']}<h1>";

$commitData = $this->fetchCommitData();

if (!$commitData) {
$this->changelog = "<p>$logContent{$this->options['noChangesMessage']}</p>";
}

if (!$this->options['tagOrderDesc']) {
$commitData = array_reverse($commitData);
}

foreach ($commitData as $tag => $data) {
// Add tag header and date.
if ($tag == 'HEAD') {
$tag = $this->options['headSubject'];
$data['date'] = $this->options['nextTagDate'];
}

$logContent .= "<h2>$tag ({$data['date']})</h2><ul>";

// No subjects present for this tag.
if (!$data['subjects']) {
$logContent .= "<li>{$this->options['noChangesMessage']}</li></ul>";
continue;
}

// Sort commit subjects.
Utilities::natSort($data['subjects'], $this->options['commitOrder']);

// Add commit subjects.
foreach ($data['subjects'] as $subjectKey => $subject) {
$logContent .= "<li>$subject (" . $this->formatHashes($data['hashes'][$subjectKey]) . ")</li>";
}

$logContent .= '</ul>';
}

$this->changelog = $logContent;
}

/**
* Format the hashes of a commit subject into a string.
*
* Each hash is formatted as defined by property formatHash.
* After formatting, all hashes are concatenated to a single line, comma separated.
*
* @param array $hashes Hashes to format
*
* @return string Formatted hash string.
* @see GitChangelog::$formatHash
*/
protected function formatHashes(array $hashes): string
{
if (!$this->options['addHashes']) {
return '';
}

foreach ($hashes as &$hash) {
$hash = str_replace('{hash}', $hash, $this->formatHash);
}
unset($hash);

return implode(', ', $hashes);
}
}

0 comments on commit 2df97ee

Please sign in to comment.