1<?php
2
3namespace Composer\Installers;
4
5use Composer\Util\Filesystem;
6
7/**
8 * Installer for Bitrix Framework. Supported types of extensions:
9 * - `bitrix-d7-module` — copy the module to directory `bitrix/modules/<vendor>.<name>`.
10 * - `bitrix-d7-component` — copy the component to directory `bitrix/components/<vendor>/<name>`.
11 * - `bitrix-d7-template` — copy the template to directory `bitrix/templates/<vendor>_<name>`.
12 *
13 * You can set custom path to directory with Bitrix kernel in `composer.json`:
14 *
15 * ```json
16 * {
17 *      "extra": {
18 *          "bitrix-dir": "s1/bitrix"
19 *      }
20 * }
21 * ```
22 *
23 * @author Nik Samokhvalov <nik@samokhvalov.info>
24 * @author Denis Kulichkin <onexhovia@gmail.com>
25 */
26class BitrixInstaller extends BaseInstaller
27{
28    protected $locations = array(
29        'module'    => '{$bitrix_dir}/modules/{$name}/',    // deprecated, remove on the major release (Backward compatibility will be broken)
30        'component' => '{$bitrix_dir}/components/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken)
31        'theme'     => '{$bitrix_dir}/templates/{$name}/',  // deprecated, remove on the major release (Backward compatibility will be broken)
32        'd7-module'    => '{$bitrix_dir}/modules/{$vendor}.{$name}/',
33        'd7-component' => '{$bitrix_dir}/components/{$vendor}/{$name}/',
34        'd7-template'     => '{$bitrix_dir}/templates/{$vendor}_{$name}/',
35    );
36
37    /**
38     * @var array Storage for informations about duplicates at all the time of installation packages.
39     */
40    private static $checkedDuplicates = array();
41
42    /**
43     * {@inheritdoc}
44     */
45    public function inflectPackageVars($vars)
46    {
47        if ($this->composer->getPackage()) {
48            $extra = $this->composer->getPackage()->getExtra();
49
50            if (isset($extra['bitrix-dir'])) {
51                $vars['bitrix_dir'] = $extra['bitrix-dir'];
52            }
53        }
54
55        if (!isset($vars['bitrix_dir'])) {
56            $vars['bitrix_dir'] = 'bitrix';
57        }
58
59        return parent::inflectPackageVars($vars);
60    }
61
62    /**
63     * {@inheritdoc}
64     */
65    protected function templatePath($path, array $vars = array())
66    {
67        $templatePath = parent::templatePath($path, $vars);
68        $this->checkDuplicates($templatePath, $vars);
69
70        return $templatePath;
71    }
72
73    /**
74     * Duplicates search packages.
75     *
76     * @param string $path
77     * @param array $vars
78     */
79    protected function checkDuplicates($path, array $vars = array())
80    {
81        $packageType = substr($vars['type'], strlen('bitrix') + 1);
82        $localDir = explode('/', $vars['bitrix_dir']);
83        array_pop($localDir);
84        $localDir[] = 'local';
85        $localDir = implode('/', $localDir);
86
87        $oldPath = str_replace(
88            array('{$bitrix_dir}', '{$name}'),
89            array($localDir, $vars['name']),
90            $this->locations[$packageType]
91        );
92
93        if (in_array($oldPath, static::$checkedDuplicates)) {
94            return;
95        }
96
97        if ($oldPath !== $path && file_exists($oldPath) && $this->io && $this->io->isInteractive()) {
98
99            $this->io->writeError('    <error>Duplication of packages:</error>');
100            $this->io->writeError('    <info>Package ' . $oldPath . ' will be called instead package ' . $path . '</info>');
101
102            while (true) {
103                switch ($this->io->ask('    <info>Delete ' . $oldPath . ' [y,n,?]?</info> ', '?')) {
104                    case 'y':
105                        $fs = new Filesystem();
106                        $fs->removeDirectory($oldPath);
107                        break 2;
108
109                    case 'n':
110                        break 2;
111
112                    case '?':
113                    default:
114                        $this->io->writeError(array(
115                            '    y - delete package ' . $oldPath . ' and to continue with the installation',
116                            '    n - don\'t delete and to continue with the installation',
117                        ));
118                        $this->io->writeError('    ? - print help');
119                        break;
120                }
121            }
122        }
123
124        static::$checkedDuplicates[] = $oldPath;
125    }
126}
127