1<?php
2
3/*
4 * This file is part of Composer.
5 *
6 * (c) Nils Adermann <naderman@naderman.de>
7 *     Jordi Boggiano <j.boggiano@seld.be>
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12
13namespace Composer\Package;
14
15use Composer\Repository\RepositoryInterface;
16use Composer\Repository\PlatformRepository;
17
18/**
19 * Base class for packages providing name storage and default match implementation
20 *
21 * @author Nils Adermann <naderman@naderman.de>
22 */
23abstract class BasePackage implements PackageInterface
24{
25    public static $supportedLinkTypes = array(
26        'require'   => array('description' => 'requires', 'method' => 'requires'),
27        'conflict'  => array('description' => 'conflicts', 'method' => 'conflicts'),
28        'provide'   => array('description' => 'provides', 'method' => 'provides'),
29        'replace'   => array('description' => 'replaces', 'method' => 'replaces'),
30        'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
31    );
32
33    const STABILITY_STABLE  = 0;
34    const STABILITY_RC      = 5;
35    const STABILITY_BETA    = 10;
36    const STABILITY_ALPHA   = 15;
37    const STABILITY_DEV     = 20;
38
39    public static $stabilities = array(
40        'stable' => self::STABILITY_STABLE,
41        'RC'     => self::STABILITY_RC,
42        'beta'   => self::STABILITY_BETA,
43        'alpha'  => self::STABILITY_ALPHA,
44        'dev'    => self::STABILITY_DEV,
45    );
46
47    /**
48     * READ-ONLY: The package id, public for fast access in dependency solver
49     * @var int
50     */
51    public $id;
52
53    protected $name;
54    protected $prettyName;
55
56    protected $repository;
57    protected $transportOptions;
58
59    /**
60     * All descendants' constructors should call this parent constructor
61     *
62     * @param string $name The package's name
63     */
64    public function __construct($name)
65    {
66        $this->prettyName = $name;
67        $this->name = strtolower($name);
68        $this->id = -1;
69        $this->transportOptions = array();
70    }
71
72    /**
73     * {@inheritDoc}
74     */
75    public function getName()
76    {
77        return $this->name;
78    }
79
80    /**
81     * {@inheritDoc}
82     */
83    public function getPrettyName()
84    {
85        return $this->prettyName;
86    }
87
88    /**
89     * {@inheritDoc}
90     */
91    public function getNames()
92    {
93        $names = array(
94            $this->getName() => true,
95        );
96
97        foreach ($this->getProvides() as $link) {
98            $names[$link->getTarget()] = true;
99        }
100
101        foreach ($this->getReplaces() as $link) {
102            $names[$link->getTarget()] = true;
103        }
104
105        return array_keys($names);
106    }
107
108    /**
109     * {@inheritDoc}
110     */
111    public function setId($id)
112    {
113        $this->id = $id;
114    }
115
116    /**
117     * {@inheritDoc}
118     */
119    public function getId()
120    {
121        return $this->id;
122    }
123
124    /**
125     * {@inheritDoc}
126     */
127    public function setRepository(RepositoryInterface $repository)
128    {
129        if ($this->repository && $repository !== $this->repository) {
130            throw new \LogicException('A package can only be added to one repository');
131        }
132        $this->repository = $repository;
133    }
134
135    /**
136     * {@inheritDoc}
137     */
138    public function getRepository()
139    {
140        return $this->repository;
141    }
142
143    /**
144     * {@inheritDoc}
145     */
146    public function getTransportOptions()
147    {
148        return $this->transportOptions;
149    }
150
151    /**
152     * Configures the list of options to download package dist files
153     *
154     * @param array $options
155     */
156    public function setTransportOptions(array $options)
157    {
158        $this->transportOptions = $options;
159    }
160
161    /**
162     * checks if this package is a platform package
163     *
164     * @return bool
165     */
166    public function isPlatform()
167    {
168        return $this->getRepository() instanceof PlatformRepository;
169    }
170
171    /**
172     * Returns package unique name, constructed from name, version and release type.
173     *
174     * @return string
175     */
176    public function getUniqueName()
177    {
178        return $this->getName().'-'.$this->getVersion();
179    }
180
181    public function equals(PackageInterface $package)
182    {
183        $self = $this;
184        if ($this instanceof AliasPackage) {
185            $self = $this->getAliasOf();
186        }
187        if ($package instanceof AliasPackage) {
188            $package = $package->getAliasOf();
189        }
190
191        return $package === $self;
192    }
193
194    /**
195     * Converts the package into a readable and unique string
196     *
197     * @return string
198     */
199    public function __toString()
200    {
201        return $this->getUniqueName();
202    }
203
204    public function getPrettyString()
205    {
206        return $this->getPrettyName().' '.$this->getPrettyVersion();
207    }
208
209    /**
210     * {@inheritDoc}
211     */
212    public function getFullPrettyVersion($truncate = true)
213    {
214        if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
215            return $this->getPrettyVersion();
216        }
217
218        // if source reference is a sha1 hash -- truncate
219        if ($truncate && strlen($this->getSourceReference()) === 40) {
220            return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
221        }
222
223        return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
224    }
225
226    public function getStabilityPriority()
227    {
228        return self::$stabilities[$this->getStability()];
229    }
230
231    public function __clone()
232    {
233        $this->repository = null;
234        $this->id = -1;
235    }
236}
237