1<?php
2/**
3 * This file is part of phpDocumentor.
4 *
5 * For the full copyright and license information, please view the LICENSE
6 * file that was distributed with this source code.
7 *
8 * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
9 * @license   http://www.opensource.org/licenses/mit-license.php MIT
10 * @link      http://phpdoc.org
11 */
12
13namespace phpDocumentor\Reflection\DocBlock\Tags;
14
15use phpDocumentor\Reflection\DocBlock\Description;
16use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
17use phpDocumentor\Reflection\Type;
18use phpDocumentor\Reflection\TypeResolver;
19use phpDocumentor\Reflection\Types\Context as TypeContext;
20use Webmozart\Assert\Assert;
21
22/**
23 * Reflection class for a {@}property-write tag in a Docblock.
24 */
25class PropertyWrite extends BaseTag implements Factory\StaticMethod
26{
27    /** @var string */
28    protected $name = 'property-write';
29
30    /** @var Type */
31    private $type;
32
33    /** @var string */
34    protected $variableName = '';
35
36    /**
37     * @param string      $variableName
38     * @param Type        $type
39     * @param Description $description
40     */
41    public function __construct($variableName, Type $type = null, Description $description = null)
42    {
43        Assert::string($variableName);
44
45        $this->variableName = $variableName;
46        $this->type = $type;
47        $this->description = $description;
48    }
49
50    /**
51     * {@inheritdoc}
52     */
53    public static function create(
54        $body,
55        TypeResolver $typeResolver = null,
56        DescriptionFactory $descriptionFactory = null,
57        TypeContext $context = null
58    ) {
59        Assert::stringNotEmpty($body);
60        Assert::allNotNull([$typeResolver, $descriptionFactory]);
61
62        $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE);
63        $type = null;
64        $variableName = '';
65
66        // if the first item that is encountered is not a variable; it is a type
67        if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) {
68            $type = $typeResolver->resolve(array_shift($parts), $context);
69            array_shift($parts);
70        }
71
72        // if the next item starts with a $ or ...$ it must be the variable name
73        if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) {
74            $variableName = array_shift($parts);
75            array_shift($parts);
76
77            if (substr($variableName, 0, 1) === '$') {
78                $variableName = substr($variableName, 1);
79            }
80        }
81
82        $description = $descriptionFactory->create(implode('', $parts), $context);
83
84        return new static($variableName, $type, $description);
85    }
86
87    /**
88     * Returns the variable's name.
89     *
90     * @return string
91     */
92    public function getVariableName()
93    {
94        return $this->variableName;
95    }
96
97    /**
98     * Returns the variable's type or null if unknown.
99     *
100     * @return Type|null
101     */
102    public function getType()
103    {
104        return $this->type;
105    }
106
107    /**
108     * Returns a string representation for this tag.
109     *
110     * @return string
111     */
112    public function __toString()
113    {
114        return ($this->type ? $this->type . ' ' : '')
115        . '$' . $this->variableName
116        . ($this->description ? ' ' . $this->description : '');
117    }
118}
119