VCS: внедрение в работу

fixxxer

К.О.
Партнер клуба
сейчас проводим испытания bitbucket.org, вроде нормально там все, пока на бесплатном тарифе, хотя, если начнем активно использовать на всех его не хватит (разве, что комбинировать пользователей между проектами).
Неужели завести бесплатный аккаунт на https://bitbucket.org/ - это проблема?
сидеть и заводить дубликаты аккаунтов из-за $10 в месяц - это какое-то феерическое нищебродство
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
fixxxer, я давно предложил сделать свой git сервачок. Им хватит даже минимального за 5 баксов.
 

fixxxer

К.О.
Партнер клуба
Без сопутствующих вебморд не круто, а потянет ли гитлаб на пятибаксовой виртуалке? Не пробовал, но не уверен.
 

scorpion-ds

Новичок
fixxxer, я давно предложил сделать свой git сервачок. Им хватит даже минимального за 5 баксов.
Ни кто не хочет отвечать за его администрирование, когда у меня был VPS иногда были проблемы, часть решал сам (иногда не быстро), другие более серьезные (или не понятные для меня) решали админы дата-центра, но там это в стоимость входило.
 

Активист

Активист
Команда форума
Активист, я тебе задаю конкретный вопрос: почему ты не имеешь никакой последовательной и единой стратегии по экранированию данных, ты мне в ответ говоришь, что native-шаблонизация делается одним методом. Ты здоровый человек? Да всем насрать одним методом или 10-ю классами: уже давно прошли времена, когда все писали всё своё. Всё уже написано, бери и пользуйся. Сколько там кода — насрать. Судя по всему, ответить тебе нечего.
Не тебе, а Вам.

Вот вам пример из реальной жизни:
PHP:
<?php // App/Estate/View/Last.phtml; ?>

<?php
/* @var $this Base_Native */
/* @var $model App_Estate_Model_List */
?>

<h3>Последние добавления</h3>

<div class="panel-body">

    <?php foreach ($model->getObjects() as $_object):?>
        <div class="pull-left">

            <?php (new App_Estate_View_Thumb($_object))->fetch();?>
   
        </div>
    <?php endforeach;?>
</div>

<?php // App/Estate/View/Thumb.php  ?>
<?php
class App_Estate_View_Thumb extends Base_View {

    protected $_template = "App/Estate/View/Thumb.phtml";

    protected $object;

    protected function __construct(Base_Estate_Interface $object)
    {
        $this->object = $object;
    }
}

?>

<?php // App/Estate/View/Thumb.phtml?>

<?php
/* @var $this Base_Native */
/* @var $object Base_Estate_Interface */
?>
<div class="app-estate-thumb app-thumb-gallery" object-id="<?php $this->echo( $object->getId() );?>">

    <a href="<?php $this->echo( $object->getPublicUri() );?>">
   
        <?php if($object->getImages()->getPrimary() ):?>
   
            <img src="<?php print $object->getImages()->getPrimary()->getUri(200, 200, true)?>">
                           
        <?php else:?>
   
            <img src="/images/camera-200px-300dpi.png" height="200px">
        <?php endif;?>
    </a>

    <ul class="app-thumb-pictures hidden">
        <?php foreach ($object->getImages() as $_image):?>
       
                <li><a    href="/bad-browser"
                        full-src="<?php $this->echo($_image->getUri(1024, 768))?>"
                        preview-src="<?php $this->echo($_image->getUri(200, 200, true));?>"
                        title="<?php $this->echo($_image->getTitle())?>"></a></li>
                   
        <?php endforeach;?>
    </ul>

</div>
Причем еще не один шаблонизатор не смог нормально обработать ArrayAccess , ни ArrayObject , ни вызов классов (видов).

От смарти из-за бажности было решено уйти еще лет пять назад.
 

scorpion-ds

Новичок
Без сопутствующих вебморд не круто, а потянет ли гитлаб на пятибаксовой виртуалке? Не пробовал, но не уверен.
Кстати вебморды важны, я сейчас отвечаю за проверку кода интернов, потому было бы удобно смотреть процесс "на месте".
 

AmdY

Пью пиво
Команда форума
Без сопутствующих вебморд не круто, а потянет ли гитлаб на пятибаксовой виртуалке? Не пробовал, но не уверен.
я же говорю - gitlab, там нормальная вебморда, тикеты, пулл реквесты, вики - бери и пользуйся. но я больше говорил про то, что есть готовые виртуалки и никаких админов не нужно. нашёл подходящую, поставил на любом сервачке и всё, готовая среда. или докер какой.

Причем еще не один шаблонизатор не смог нормально обработать ArrayAccess , ни вызов классов (видов).
не верю. arrayaccess как раз и создан, чтобы внешне не было разницы между объектом и массивов. Разве что вы криво его имплементировали, например, забыв об __isset
 

scorpion-ds

Новичок
я же говорю - gitlab, там нормальная вебморда, тикеты, пулл реквесты, вики - бери и пользуйся. но я больше говорил про то, что есть готовые виртуалки и никаких админов не нужно. нашёл подходящую, поставил на любом сервачке и всё, готовая среда. или докер какой.
Ты имеешь ввиду уже настроенные образы git + gitlab?
 

Вурдалак

Продвинутый новичок
PHP:
<img src="<?php print $object->getImages()->getPrimary()->getUri(200, 200, true)?>">
PHP:
preview-src="<?php $this->echo($_image->getUri(200, 200, true));?>"
Да ты даже не можешь специально пример на форум выложить, где всё будет последовательно, уже тут мечешься писать через $this->echo() или явно.

Причем еще не один шаблонизатор не смог нормально обработать ArrayAccess , ни вызов классов (видов).
Иди сказки другим рассказывай, как будто от шаблонизатора что-то требуется такое особенное для поддержки.

вызов классов (видов).
«Вызов классов»? Ты про это:
PHP:
<?php (new App_Estate_View_Thumb($_object))->fetch();?>
?
[...]
 

Активист

Активист
Команда форума
я же говорю - gitlab, там нормальная вебморда, тикеты, пулл реквесты, вики - бери и пользуйся. но я больше говорил про то, что есть готовые виртуалки и никаких админов не нужно. нашёл подходящую, поставил на любом сервачке и всё, готовая среда. или докер какой.
не верю. arrayaccess как раз и создан, чтобы внешне не было разницы между объектом и массивов. Разве что вы криво его имплементировали, например, забыв об __isset
Я иногда использую ArrayAccess, но очень часто и много использую ArrayObject , и не хочу что бы работали автокомплиты, но увы, ни один шаблонизатор не способен обеспечить автокомлит, да и с подсветкой синтаксиса проблемы...

Например, я хочу использвать обе конструкции
PHP:
// И доступ к конкретному объекту через ArrayObject
<?php $object->getImages()->getPrimary()->getUri(200, 200, true); ?>

// Так и работать с объектами как с массивами
<?php foreach ($object->getImages() as $_image):?>
PHP:
<?php
class app_images_array extends ArrayObject
{
    function __construct($array)
    {
        parent::setFlags(parent::ARRAY_AS_PROPS);
        parent::__construct($array);
    }
  
    /**
    * Устанавливает главную фотографию по id
    * @param int $id
    * @return app_images_array
    */
    public function setPrimary($id)
    {
        foreach ($this as $object)
        {
            if ($object->getId() == $id)
            {
                $object->setPrimary(true)->save();
            }
        }
      
        foreach ($this as $object)
        {
            if ($object->getId() != $id && $object->getPrimary())
            {
                $object->setPrimary(false)->save();
            }
        }
      
        return $this;
    }
  
    /**
    * Устанавливает главную фотографию
    * @return app_images_image|boolean
    */
    public function getPrimary()
    {
        foreach ($this as $object)
        {
            if ($object->getPrimary())
            {
                return $object;
            }
        }
      
        foreach ($this as $object)
        {
            return $object;
        }
      
        return false;
    }
  
    /**
    * Возвращает изображения
    * @return multitype:app_images_image
    */
    public function getNonPrimary()
    {
        $objects = array();
      
        foreach ($this as $object)
        {
            if ($object->getPrimary())
            {
                continue;
            }
          
            $objects[] = $object;
        }
      
        return $objects;
    }
}
PHP:
<?php 
trait app_object_images
{
    /**
    * Содержит изобржения для объекта
    * @var app_images_image[]
    */
    protected $_images;
   
    /**
    * Метод возвращает директорию, куда необходимо сохранить файлы
    * @return string 
    */
    abstract function getImagesUploadDirectory();
   
    /**
    * Возвращает данные 
    */
    abstract function getImagesRatio();
   
   
    public function userInputImages($_images)
    {
        if (is_array($_images) && isset($_images['id']))
        {
            $increment = 0;
           
            foreach ($_images['id'] as $_key => $_id)
            {
                if (
                    !isset($_images['id'][$_key])        || !isset($_images['name'][$_key])    || !isset($_images['filename'][$_key])    || !isset($_images['primary'][$_key])
                ||    !isset($_images['title'][$_key])    || !isset($_images['width'])        || !isset($_images['height'])            || !isset($_images['kx1'][$_key])
                ||    !isset($_images['ky1'][$_key])        || !isset($_images['kx2'][$_key])    || !isset($_images['ky2'][$_key])        || !isset($_images['xHumb'][$_key])
                ||    !$_images['name'][$_key]            || !$_images['filename'][$_key]
                )
                {
                    continue;
                }
       
                if (!$_images['id'][$_key])
                {
                    if (!($image = $this->addImage($_images['name'][$_key], $_images['filename'][$_key])))
                    {
                        continue;
                    }
                   
                    if ($_images['primary'][$_key])
                    {
                        foreach ($this->getImages() as $image)
                        {
                            $image->setPrimary(false);
                        }
                    }
                   
                    $image
                    ->setXHumb($_images['xHumb'][$_key])
                    ->setPrimary($_images['primary'][$_key])
                    ->setTitle($_images['title'][$_key])
                    ->setRatio($this->getImagesRatio())
                    ->setKx1($_images['kx1'][$_key])
                    ->setKy1($_images['ky1'][$_key])
                    ->setKx2($_images['kx2'][$_key])
                    ->setKy2($_images['ky2'][$_key])
                    ;
                }
                else
                {
                    if ($image = $this->getImageById($_images['id'][$_key]))
                    {
                        $image
                        ->setTitle($_images['title'][$_key])
                        ->setPrimary($_images['title'][$_key])
                        ;
                    }
                }
            }
        }
   
        return $this;
    }
   
    /**
    * Добавляем новое изображение
    * @param string $name
    * @param string $filename
    * @return boolean|app_images_image
    */
    public function addImage($name, $filename)
    {
        $this->getImages();
       
        if (!file_exists($filename))
        {
            $this->addError("Файл [$filename] не существует");
            return false;
        }
       
        if (!is_readable($filename))
        {
            $this->addError("Файл [$filename] не доступен для записи");
            return false;
        }
       
        if (!($imageInfo = getimagesize($filename)))
        {
            $this->addError("Изображение не допустимого формата #1");
            return false;
        }
       
        if (!$imageInfo[0] || !$imageInfo[1])
        {
            $this->addError("Изображение не допустимого формата #2");
            return false;
        }
       
        return 
        $this->_images[]
        =
        (new app_images_image())
        ->setTempFilename($filename)
        ->setClass(get_class($this))
        ->setObjectId($this->getId())
        ->setName($name)
        ->setFilename(basename($filename))
        ->setWidth($imageInfo[0])
        ->setHeight($imageInfo[1])
        ->setPosition(sizeof($this->getImages()))
        ;
    }
   
    public function storeAndSaveImages()
    {
        if (!isset($this->_images) || !is_array($this->_images))
        {
            return $this;
        }
       
        if (!$this->getImagesUploadDirectory())
        {
            throw app_exception("Метод сохранения изображений не может получить директорию для записи", 503);
        }
       
        foreach ($this->_images as $image)
        {
            if (!$image->getId())
            {
                if (!$this->getId())
                {
                    throw new app_exception("Ой.. Не смог скопировать изображения. Не определен id объекта", 503);
                }
               
                if (!$image->getTempFilename())
                {
                    throw new app_exception("Ой.. Не смог скопировать изображения. Не определен getTempFailename()", 503);
                }
               
                $src = $image->getTempFilename();
                $dst = $this->getImagesUploadDirectory().(substr($this->getImagesUploadDirectory(), -1, 1) != DIRECTORY_SEPARATOR ? "/" : null).$image->getFilename();
               
                if (!file_exists($src) || !is_file($src) || !is_readable($src))
                {
                    throw new app_exception("Ой.. Файл {$src} не существует или не доступн для чтения", 503);
                   
                }
               
                if (!file_exists(dirname($dst)) || !is_dir(dirname($dst)) || !is_writable(dirname($dst)))
                {
                    throw new app_exception("Ой.. Директория ".dirname($dst)." не существует или не доступна для записи", 503);
                } 
               
                if (!copy($src, $dst))
                {
                    throw new app_exception("Ой.. Не смог скопировать {$src} в {$dst} не существует или не доступна для записи", 503);
                }
               
                $image
                ->setObjectId($this->getId())
                ->setDirectory(dirname($dst))
                ->save()
                ;
            }
            else 
            {
                $image->save();
            }
        }
    }
   
    public function setImages(array $images)
    {
        $this->_images = $images;
        return $this;
    }
   
    /**
    * Получаем изображения из базы данных
    * @return app_images_images|multitype:app_images_array
    */
    public function getImages()
    {
        if (isset($this->_images))
        {
            return new app_images_array($this->_images);
        }
   
        if (!$this->getId())
        {
            return new app_images_array(array());
        }
   
        $this->_images = array();
   
        $db = (new app_db())->query("SELECT * FROM `app_images_image` WHERE `class` = '".get_class($this)."' && `objectId` = '".$this->getId()."' ORDER BY `position`");
        while ($row = $db->fetch())
        {
            $this->_images[] = (new app_images_image())->setAttributes($row);
        }
   
        return new app_images_array($this->_images);
    }
}
 
Последнее редактирование:

hell0w0rd

Продвинутый новичок
Активист, ArrayObject - нативная реализации ArrayAccess. Twig уже давно умеет работать с любыми объектами, и любыми вариантами получения их свойств
 

AmdY

Пью пиво
Команда форума
Активист, посмотри на свои шаблоны, помимо ескейпинга у тебя вылазит вторая проблема нативных шаблонизаторов - провоцирование сложной логики в шаблонах. Ну и как бы есть готовый блейд, который и шаблонизатор и php позволяет городить, так что и здесь есть готовое.
 

Активист

Активист
Команда форума
А вы вот так попробуйте в svn одну ветку, которая до транка догонялась, смержить в другую которая тоже до транка догонялась.
svn merge --reintegrate

Активист, ты вообще Twig пробовал, или делаешь выводы по у*бищному смарти?
После Smarty юзать шаблонизаторы нет ни какого желания. А после привыкания к автокомплитам IDE, переходить на что-то другое никого желания.

Активист, посмотри на свои шаблоны, помимо ескейпинга у тебя вылазит вторая проблема нативных шаблонизаторов - провоцирование сложной логики в шаблонах. Ну и как бы есть готовый блейд, который и шаблонизатор и php позволяет городить, так что и здесь есть готовое.
Не вижу там логики? В чем сложность шаблона? В вызове методов?
 

fixxxer

К.О.
Партнер клуба
После Smarty юзать шаблонизаторы нет ни какого желания
Ай, после просмотра исходного кода смарти вообще повеситься может захотеться. Не стоит делать общий вывод по говенной частности.
 

Активист

Активист
Команда форума
Т.е. не пробовали, понятно.
В чем проблема. Транк мерджится с веткой, commit. Вторая ветка reintegrate с trunk, commit. Далее мердж транка со второй веткой. Не возникало сложностей. Бывают конфликты, но они естественные. Tree конфликтов тоже нет.
 
Сверху