1<?php
2
3/**
4 * Hoa
5 *
6 *
7 * @license
8 *
9 * New BSD License
10 *
11 * Copyright © 2007-2017, Hoa community. All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
15 *     * Redistributions of source code must retain the above copyright
16 *       notice, this list of conditions and the following disclaimer.
17 *     * Redistributions in binary form must reproduce the above copyright
18 *       notice, this list of conditions and the following disclaimer in the
19 *       documentation and/or other materials provided with the distribution.
20 *     * Neither the name of the Hoa nor the names of its contributors may be
21 *       used to endorse or promote products derived from this software without
22 *       specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37namespace Hoa\File\Link;
38
39use Hoa\Consistency;
40use Hoa\File;
41
42/**
43 * Class \Hoa\File\Link.
44 *
45 * Link handler.
46 *
47 * @copyright  Copyright © 2007-2017 Hoa community
48 * @license    New BSD License
49 */
50class Link extends File
51{
52    /**
53     * Open a link.
54     *
55     * @param   string  $streamName    Stream name.
56     * @param   string  $mode          Open mode, see the parent::MODE_*
57     *                                 constants.
58     * @param   string  $context       Context ID (please, see the
59     *                                 \Hoa\Stream\Context class).
60     * @param   bool    $wait          Differ opening or not.
61     * @throws  \Hoa\File\Exception
62     */
63    public function __construct(
64        $streamName,
65        $mode,
66        $context = null,
67        $wait    = false
68    ) {
69        if (!is_link($streamName)) {
70            throw new File\Exception(
71                'File %s is not a link.',
72                0,
73                $streamName
74            );
75        }
76
77        parent::__construct($streamName, $mode, $context, $wait);
78
79        return;
80    }
81
82    /**
83     * Get informations about a link.
84     *
85     * @return  array
86     */
87    public function getStatistic()
88    {
89        return lstat($this->getStreamName());
90    }
91
92    /**
93     * Change file group.
94     *
95     * @param   mixed   $group    Group name or number.
96     * @return  bool
97     */
98    public function changeGroup($group)
99    {
100        return lchgrp($this->getStreamName(), $group);
101    }
102
103    /**
104     * Change file owner.
105     *
106     * @param   mixed   $user   User.
107     * @return  bool
108     */
109    public function changeOwner($user)
110    {
111        return lchown($this->getStreamName(), $user);
112    }
113
114    /**
115     * Get file permissions.
116     *
117     * @return  int
118     */
119    public function getPermissions()
120    {
121        return 41453; // i.e. lrwxr-xr-x
122    }
123
124    /**
125     * Get the target of a symbolic link.
126     *
127     * @return  \Hoa\File\Generic
128     * @throws  \Hoa\File\Exception
129     */
130    public function getTarget()
131    {
132        $target    = dirname($this->getStreamName()) . DS .
133                     $this->getTargetName();
134        $context   = null !== $this->getStreamContext()
135                         ? $this->getStreamContext()->getCurrentId()
136                         : null;
137
138        if (true === is_link($target)) {
139            return new ReadWrite(
140                $target,
141                File::MODE_APPEND_READ_WRITE,
142                $context
143            );
144        } elseif (true === is_file($target)) {
145            return new File\ReadWrite(
146                $target,
147                File::MODE_APPEND_READ_WRITE,
148                $context
149            );
150        } elseif (true === is_dir($target)) {
151            return new File\Directory(
152                $target,
153                File::MODE_READ,
154                $context
155            );
156        }
157
158        throw new File\Exception(
159            'Cannot find an appropriated object that matches with ' .
160            'path %s when defining it.',
161            1,
162            $target
163        );
164    }
165
166    /**
167     * Get the target name of a symbolic link.
168     *
169     * @return  string
170     */
171    public function getTargetName()
172    {
173        return readlink($this->getStreamName());
174    }
175
176    /**
177     * Create a link.
178     *
179     * @param   string  $name      Link name.
180     * @param   string  $target    Target name.
181     * @return  bool
182     */
183    public static function create($name, $target)
184    {
185        if (false != linkinfo($name)) {
186            return true;
187        }
188
189        return symlink($target, $name);
190    }
191}
192
193/**
194 * Flex entity.
195 */
196Consistency::flexEntity('Hoa\File\Link\Link');
197