Commit 31031681 authored by Sean Madsen's avatar Sean Madsen

refactor - web-based publishing now working

parent 1e9da6a0
......@@ -9,7 +9,7 @@ services:
class: AppBundle\Model\Library
arguments:
- %kernel.root_dir%/config/books
github.hook.processor:
class: AppBundle\Utils\GitHubHookProcessor
arguments:
......@@ -22,7 +22,7 @@ services:
- '@request_stack'
- '@publish.logger'
- '@filesystem'
- %kernel.root_dir%/config/books
- '@library'
- %publisher_repos_dir%
- %kernel.root_dir%/../web/static
......
......@@ -28,9 +28,10 @@ class PublishController extends Controller {
* })
*/
public function PublishAction(Request $request, $lang, $book, $branch) {
/** @var \AppBundle\Utils\Publisher $publisher */
$publisher = $this->get('publisher');
$publisher->publish($book, $lang, $branch);
$content['messages'] = $publisher->getMessages();
$content['messages'] = $publisher->messages;
return $this->render('AppBundle:Publish:publish.html.twig', $content);
}
......@@ -42,8 +43,6 @@ class PublishController extends Controller {
$event = $request->headers->get('X-GitHub-Event');
$payload = json_decode($body);
$books = $this->get('book.loader')->find();
$processor = $this->get('github.hook.processor');
$processor->process($event, $payload);
if (!$processor->published) {
......
......@@ -3,50 +3,46 @@
namespace AppBundle\Model;
use Symfony\Component\Yaml\Parser;
use AppBundle\Utils\StringTools;
class Book {
/**
* @var string $shortName The reference identifier for this book, taken from
* the name of the book's .yml file.
* @var string The reference identifier for this book, taken from
* the name of the book's .yml file.
*/
public $slug;
/**
* @var string $fullName The title of the book, taken from the "name"
* attribute in the book's .yml file.
* @var string The title of the book, taken from the "name"
*/
public $name;
/**
* @var string $description Description of the book taken from the
* "description" attribute in the book's .yml file
* and displayed on the home page.
* @var string Short phrase describing the book, taken from the
*/
public $description;
/**
* @var array $languages An array (without keys of Language objects to
* represent the available languages for the book.
* @var array An array (without keys of Language objects to
*/
public $languages;
/**
*
* @var int $weight Used to sort books
* @var int Used to sort books
*/
public $weight;
/**
* Creates a book based on a yaml conf file
*
* @param string $confFile The path to the yaml configuration file which
*
* @param string $confFile The path to the yaml configuration file which
* defines the attributes of the book.
*/
public function __construct($confFile) {
$parser = new Parser();
$yaml = $parser->parse(file_get_contents($confFile));
$this->slug = basename($confFile, '.yml');
$this->slug = StringTools::urlSafe(basename($confFile, '.yml'));
$this->name = $yaml['name'];
$this->weight = isset($yaml['weight']) ? $yaml['weight'] : 0;
$this->description = isset($yaml['description']) ? $yaml['description'] : "";
......@@ -61,4 +57,23 @@ class Book {
public function isMultiLanguage(){
return count($this->languages) > 1;
}
/**
* Selects one of the languages within the book
*
* @param string $code Two letter language code to describe the language
*
* @return Language
*/
public function getLanguageByCode($code) {
$chosen = NULL;
foreach($this->languages as $language) {
if($language->code == $code) {
$chosen = $language;
break;
}
}
return $chosen;
}
}
......@@ -2,58 +2,128 @@
namespace AppBundle\Model;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use AppBundle\Utils\LocaleTools;
use \AppBundle\Model\Version;
class Language extends ContainerAwareCommand {
class Language {
/**
*
* @var string $repo The URL to the git repository for this language
* @var string The URL to the git repository for this language
*/
public $repo;
/**
*
* @var array $versions An array (without keys) of Version objects
* @var array An array (without keys) of Version objects
*/
public $versions;
/**
*
* @var string $code The two letter language code for this language as
* specified by https://en.wikipedia.org/wiki/ISO_639-1
* @var string The two letter language code for this language as
* specified by https://en.wikipedia.org/wiki/ISO_639-1
*/
public $code;
/**
* Initialize a language with values in it. This function is separate from the
* constructor function only so that we have have a "language" service which
* gets the $localesDir passed in when the service is retrieved.
*
* Initialize a language with values in it.
*
* @param string $code two letter language code
* @param array $yaml language data from a book's yaml file
*/
public function __construct($code, $yaml) {
$this->code = $code;
$this->repo = $yaml['repo'];
$this->setupVersions($yaml);
}
/**
* Set up $this->versions based on parsed yaml data in $yaml
*
* @param array $yaml Data passed into the language constructor.
*/
private function setupVersions($yaml) {
$latestBranch = isset($yaml['latest']) ? $yaml['latest'] : NULL;
$stableBranch = isset($yaml['stable']) ? $yaml['stable'] : NULL;
if ($latestBranch) {
$this->versions[] = new Version('latest', $latestBranch);
$history = isset($yaml['history']) ? $yaml['history'] : array();
if ($latestBranch && $stableBranch) {
if ($latestBranch == $stableBranch) {
$this->addVersion('latest', $latestBranch,
array('stable'));
}
else {
$this->addVersion('latest', $latestBranch);
$this->addVersion('stable', $stableBranch);
}
}
if ($stableBranch != $latestBranch) {
$this->versions[] = new Version('stable', $stableBranch);
elseif ($latestBranch) {
$this->addVersion('latest', $latestBranch);
}
elseif ($stableBranch) {
$this->addVersion('stable', $latestBranch);
}
$history = isset($yaml['history']) ? $yaml['history'] : array();
foreach ($history as $item) {
$this->versions[] = new Version($item);
$this->addVersion($item);
}
if (count($this->versions) == 0) {
$this->addVersion('latest', 'master');
}
}
/**
* Check this language for any problems in the way it's defined.
*
* If validation succeeds, this function returns nothing
*
* If validation fails, this function throws an exception.
*/
public function validate() {
$this->validateCode();
$this->validateVersions();
}
private function validateCode() {
if (!LocaleTools::codeIsValid($this->code)) {
throw new Exception("Language code '{$this->code}' is not a valid "
. "ISO 639-1 code.");
}
}
/**
* Adds a new version to this branch
*
* @param string $name (e.g. "latest", "master", "4.7", etc.)
* @param string $branch (e.g "master", "4.7", etc)
* @param array $aliases Array of strings containing names which can also be
* used to reference the version.
*/
public function addVersion($name, $branch = NULL, $aliases = array()) {
$this->versions[] = new Version($name, $branch, $aliases);
}
/**
* Check all versions within this language to make sure there are no
* collisions between name/branch/aliases across different versions.
*
* If validation succeeds, this function returns nothing
*
* If validation fails, this function throws an exception.
*/
private function validateVersions() {
$descriptors = array();
foreach ($this->versions as $version) {
$descriptors = array_merge($descriptors, $version->allDescriptors());
}
$duplicateDescriptors
= array_diff_assoc($descriptors, array_unique($descriptors));
if ($duplicateDescriptors) {
throw new Exception(
"Duplicate descriptors '" . implode(", ", $duplicateDescriptors)
. "' found for the versions defined within language '{$this->code}'");
}
}
/**
* The name of the language, in English (e.g. "Spanish")
*
*
* @return string
*/
public function englishName() {
......@@ -62,13 +132,13 @@ class Language extends ContainerAwareCommand {
/**
* The native name of the language, in the language (e.g. "Español")
*
*
* @return string
*/
*/
public function nativeName() {
return LocaleTools::getLaguageNameInLocale($this->code, $this->code);
}
public function descriptiveName() {
if($this->code == 'en') {
return $this->englishName();
......@@ -77,14 +147,31 @@ class Language extends ContainerAwareCommand {
return $this->nativeName() . " (" . $this->englishName() . ")";
}
}
/**
* True when this language contains multiple distinct versions.
*
*
* @return bool
*/
public function isMultiVersion() {
return count($this->versions) > 1;
}
/**
*
* @param string $branch
* @return \AppBundle\Model\Version The first version in $versions which
* matches the specified branch
*/
public function getVersionByBranch($branch) {
$chosen = NULL;
foreach($this->versions as $version) {
if($version->branch == $branch) {
$chosen = $version;
break;
}
}
return $chosen;
}
}
......@@ -8,15 +8,15 @@ class Library {
/**
*
* @var array $books An array (without keys) of Book objects to represent all
* the books in the system.
* @var array An array (without keys) of Book objects to represent all the
* books in the system.
*/
public $books;
/**
* Build a new Library based on a directory of book conf files.
*
* @param type $configDir
* @param strig $configDir
*/
public function __construct($configDir) {
$finder = new Finder();
......@@ -81,4 +81,22 @@ class Library {
return $rows;
}
/**
* Selects one of the many books within the library
*
* @param string $slug The short name describing the book
*
* @return Book
*/
public function getBookBySlug($slug) {
$chosen = NULL;
foreach ($this->books as $book) {
if ($book->slug == $slug) {
$chosen = $book;
break;
}
}
return $chosen;
}
}
......@@ -2,41 +2,92 @@
namespace AppBundle\Model;
/**
* Description of Version
*
*/
use AppBundle\Utils\StringTools;
class Version {
/**
*
* @var string $name Version name (e.g. "4.6" or "latest"). This is what
* readers see. Sometimes it's the same as name of the
* branch, but not always.
* @var string Version name (e.g. "4.6" or "latest"). This is what
* readers see. Sometimes it's the same as name of the
* branch, but not always.
*/
public $name;
/**
*
* @var string $branch The git branch that corresponds to this version
* (e.g. "master" or "4.6"). Sometimes it's the same as
* $name but not always.
* @var string The git branch that corresponds to this version
* (e.g. "master" or "4.6"). Sometimes it's the same as
* $name but not always.
*/
public $branch;
/**
*
* @var array $aliases An array (without keys) of strings which represent
* aliases to this version of the book. For each alias,
* we will create symbolic links so that a reader can also
* access this version of the book at a URL with that
* alias.
* @var array An array (without keys) of strings which represent
* aliases to this version of the book. For each alias,
* we will create symbolic links so that a reader can also
* access this version of the book at a URL with that
* alias.
*/
public $aliases;
/**
* Defines a new "version" of a book, with aliases.
*
* A version has one and only
* one "branch", meaning the git branch used for the version. A version also
* can have many "aliases", which are other descriptors like "stable" that we
* can also use to refer to this version. When the book gets published, its
* files live in a directory named after the branch. Then we create symbolic
* links to this directory for each of the aliases. So if the branch is
* "master" and we have an alias called "stable", then the book will be
* accessible at "master" via the directory and at "stable" via the symlink.
*
* If the constructor receives different $name and $branch values, it will
* automatically add an alias for $name.
*
* @param string $name (e.g. "latest", "master", "4.7", etc.)
* @param string $branch (e.g "master", "4.7", etc)
* @param array $aliases Array of strings containing names which can also be
* used to reference this version.
*/
public function __construct($name, $branch = NULL, $aliases = array()) {
$this->name = $name;
$this->branch = $branch ?: $name;
$this->aliases = $aliases;
$this->setupAliases($aliases);
}
private function setupAliases($aliases) {
// wrap $aliases in array, if necessary
if (!is_array($aliases)) {
$aliases = array($aliases);
}
// Add an alias for $name if necessary
if ($this->name != $this->branch && !isset($aliases[$this->name])) {
$aliases[] = $this->name;
}
// Remove alias for $branch if it exists
unset($aliases[$this->branch]);
// Make sure each alias is URL-safe
foreach ($aliases as &$alias) {
$alias = StringTools::urlSafe($alias);
}
$this->aliases = array_unique($aliases);
}
/**
* Gives an array of all unique strings that can be used to describe this
* version, including branch, name, and any aliases.
*
* @return array of strings (without keys)
*/
public function allDescriptors() {
$result = $this->aliases;
$result[] = $this->name;
$result[] = $this->branch;
return array_unique($result);
}
}
......@@ -9,23 +9,33 @@ define('locales_dir', __DIR__ . '/../../../vendor/symfony/symfony/src/Symfony/Co
*
*/
class LocaleTools {
const LOCALES_DIR = locales_dir;
/**
* Returns the name of a language, in another language. For example, if
* Returns the name of a language, in another language. For example, if
* $languageCode = 'en' and $localeCode = 'es' this function would answer the
* question "what word do Spanish-speaking people use to refer to English?"
*
*
* @param type $languageCode The language we're asking about
* @param type $localeCode The language in which we want our answer
*
* @return string
*
* @return string
*/
public static function getLaguageNameInLocale($languageCode, $localeCode) {
$localesFiles = self::LOCALES_DIR . "/$localeCode.json";
$locales = json_decode(file_get_contents($localesFiles), TRUE);
$localeFile = self::LOCALES_DIR . "/$localeCode.json";
$locales = json_decode(file_get_contents($localeFile), TRUE);
return $locales['Names'][$languageCode];
}
/**
* Checks to see whether a given language code is a valid ISO-639-1 code.
*
* @param string $languageCode (e.g. "en", or "es")
* @return boolean TRUE if the code is valid
*/
public static function codeIsValid($languageCode) {
return file_exists(self::LOCALES_DIR . "/$languageCode.json");
}
}
This diff is collapsed.
<?php
namespace AppBundle\Utils;
/**
* Description of StringTools
*
* @author sean
*/
class StringTools {
/**
* Cleans up strings to be used for within URLs. For example, it makes them
* lowercase and replaces spaces with dashes.
*
* @param string $s the string to clean up
*
* @return string The cleaned string, safe for use in URLs
*/
public static function urlSafe($s) {
$clean = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($s)));
$clean = preg_replace('#[^a-zA-Z0-9/_|+ -]#', '', $clean);
$clean = preg_replace('#[/_|+ -]+#', '-', $clean);
return $clean;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment