Version.php 4.3 KB
Newer Older
Sean Madsen's avatar
Sean Madsen committed
1 2 3 4
<?php

namespace AppBundle\Model;

5 6
use AppBundle\Utils\StringTools;

Sean Madsen's avatar
Sean Madsen committed
7 8 9
class Version {

  /**
Sean Madsen's avatar
Sean Madsen committed
10
   * @var string
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
   *   The machine readable name of this version. For example, in a book with
   *   multiple versions, the slug should be defined to correspond to the
   *   version numbers of the product (i.e. "4.7", or "4.6"). The slug can be
   *   "master" if a book is only using one version.
   */
  public $slug;

  /**
   * @var string
   *   This is the URL component for the published book. If it's not defined
   *   in the book's yaml file, then we use $slug as the path component.
   */
  public $path;

  /**
   * @var string
   *   A human-readable name of this version (e.g. "4.7 / Current" or "latest").
   *   This is what readers see.
Sean Madsen's avatar
Sean Madsen committed
29 30
   *   Sometimes it's the same as name of the branch, but not always. It can
   *   contain pretty much whatever characters you want.
Sean Madsen's avatar
Sean Madsen committed
31 32
   */
  public $name;
33

Sean Madsen's avatar
Sean Madsen committed
34
  /**
Sean Madsen's avatar
Sean Madsen committed
35 36 37 38 39
   * @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. It can be any string
   *   that actually maps to a real git branch, including strings with forward
   *   slashes.
Sean Madsen's avatar
Sean Madsen committed
40 41
   */
  public $branch;
42

Sean Madsen's avatar
Sean Madsen committed
43
  /**
Sean Madsen's avatar
Sean Madsen committed
44
   * @var string[]
45 46 47 48 49
   *   An array (without keys) of strings which represent redirects to this
   *   version of the book.
   *   (e.g. ["latest", "current"])
   *   If a reader requests a page with one of these redirects in place of the
   *   $path, then the app will redirect them to the proper page.
Sean Madsen's avatar
Sean Madsen committed
50
   */
51
  public $redirects;
Sean Madsen's avatar
Sean Madsen committed
52

53 54 55 56 57 58 59 60 61 62 63 64 65
  /**
   * 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.
   *
66
   * @param string $slug
Sean Madsen's avatar
Sean Madsen committed
67
   *   @see Version::slug
Sean Madsen's avatar
Sean Madsen committed
68
   * @param string $name
Sean Madsen's avatar
Sean Madsen committed
69
   *   @see Version::name
70
   * @param null $path
Sean Madsen's avatar
Sean Madsen committed
71
   *   @see Version::path
Sean Madsen's avatar
Sean Madsen committed
72
   * @param string $branch
Sean Madsen's avatar
Sean Madsen committed
73
   *   @see Version::branch
74
   * @param array $redirects
Sean Madsen's avatar
Sean Madsen committed
75
   *   @see Version::redirects
76
   */
77 78
  public function __construct($slug = 'latest', $name = 'Latest', $path = NULL, $branch = 'master', $redirects = []) {
    $this->slug = $slug;
Sean Madsen's avatar
Sean Madsen committed
79
    $this->name = $name;
80 81 82
    $this->path = $path ?? $slug;
    $this->branch = $branch;
    $this->setupRedirects($redirects);
Sean Madsen's avatar
Sean Madsen committed
83
  }
84

Sean Madsen's avatar
Sean Madsen committed
85
  /**
86
   * @param $redirects array|string
Sean Madsen's avatar
Sean Madsen committed
87 88
   *   e.g. "latest"
   */
89
  private function setupRedirects($redirects) {
90
    // wrap $aliases in array, if necessary
91 92
    if (!is_array($redirects)) {
      $redirects = array($redirects);
93 94
    }

95 96
    // Add alias for $branch (e.g. so urls with "master" will work correctly)
    $redirects[] = $this->branch;
97

98 99 100
    // Add alias for $slug (e.g. so urls with "4.7" will work correctly)
    $redirects[] = $this->slug;

101
    // Make sure each alias is URL-safe
102 103
    foreach ($redirects as &$redirect) {
      $redirect = StringTools::urlSafe($redirect);
104 105
    }

Sean Madsen's avatar
Sean Madsen committed
106
    // Make sure we don't have any duplicate redirects
107
    $this->redirects = array_unique($redirects);
Sean Madsen's avatar
Sean Madsen committed
108 109 110

    // Ensure that $path is not a redirect (to avoid infinite redirect loops)
    $this->redirects = array_diff($this->redirects, [$this->path]);
111 112 113 114
  }

  /**
   * Gives an array of all unique strings that can be used to describe this
115
   * version, including the path plus any aliases.
116
   *
Sean Madsen's avatar
Sean Madsen committed
117 118
   * @return array
   *   Array of strings (without keys)
119 120
   */
  public function allDescriptors() {
121 122
    $result = $this->redirects;
    $result[] = $this->path;
123 124 125
    return array_unique($result);
  }

126 127 128 129 130 131

  /**
   * Check this version for any problems in the way it's defined.
   *
   * If validation succeeds, this function returns nothing
   *
Sean Madsen's avatar
Sean Madsen committed
132 133
   * @throws \Exception
   *   If validation fails
134 135 136
   */
  public function validate() {
    if (preg_match("#/#", $this->branch)) {
137
      throw new \Exception("Branch name can not contain a forward slash.");
138 139 140
    }
  }

Sean Madsen's avatar
Sean Madsen committed
141
}