За последние 24 часа нас посетили 18356 программистов и 1654 робота. Сейчас ищут 1770 программистов ...

Бланки в ВЕБ-приложении

Тема в разделе "Решения, алгоритмы", создана пользователем Villan, 13 апр 2011.

  1. Villan

    Villan Активный пользователь

    С нами с:
    13 апр 2011
    Сообщения:
    36
    Симпатии:
    0
    Решил я намедни задачку и, похоже, красиво. Может, кто заинтересуется.

    Организации, как известно, плодят всякие бланки для распечатки и/или высылки по почте. Как те, которые требует родное государство, так и сочинённые самостоятельно для пользы дела. И очень хотят, чтобы их рабочая программа также их выплёвывала.

    Если нужен один-два бланка -- можно написать код, который их будет генерить. Но если их МНОГО - тогда нужно решение, подобное тому, что придумал я.

    В основе, разумеется, до блеска обсосанная на этом форуме шаблонизация. Но, как мне кажется, всё же с изюминкой.

    Изюминка - это абстрактный класс printable - в котором есть вся функциональность для генерации бланка. Если объект хочет генерить бланки - ему всего лишь надо унаследоваться от printable.

    А шаблон представляет собой HTML-файл с разметкой - особенность которой в том, что в качестве маркеров выступают имена свойств и методов класса-наследника printable. на место которых ставится текст, который они возвращают.

    И есть два режима формирования бланка -- редактирование и печать. Это делается затем, чтобы бланк можно было отредактировать перед сохранением, не меняя ничего в базе данных.

    * * *
    Ну вот я изложил главное содержание идеи. Но я её год откатывал - занимаясь мелочами. И теперь мне даже самому нравится, как всё это работает.

    Так что могу ответить на вопросы и по этим мелочам.
     
  2. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    Покажи пример использования (в коде). Интересно.
     
  3. Villan

    Villan Активный пользователь

    С нами с:
    13 апр 2011
    Сообщения:
    36
    Симпатии:
    0
    Ну сам класс 711 строк, и в основном банальности (типа чтения файлов в папке и выведение их в SELECT).

    Я покажу методы, которые заменяют маркеры в шаблоне на значения.

    Вот примеры таких маркеров:

    ##status## -- заменяется на свойство status, изменить при редактировании бланка нельзя
    %%status%% -- заменяется на свойство status, изменить при редактирвоании бланка можно

    ##output(2)## -- заменяется на результат метода output(), изменить при редактировании бланка нельзя
    %%output(2)%% -- заменяется на результат метода output(), изменить при редактировании бланка можно

    Думаю, логика ясна. А теперь методы класса printable

    PHP:
    1. //------ Формирование html-коду бланка---------------------------------
    2. public function blank($mode=self::printer)  
    3.     {
    4.  
    5.     $this->blank_folder(); // получение папки с шаблонами
    6.     $file=$this->template_folder().'/index.html';
    7.     $html=file_get_contents($file);  //получение html-кода шаблона
    8.  
    9.     if($html===false)
    10.         {
    11.         return 'Error of reading '.$file;
    12.         }
    13.  
    14. /*
    15. После редактирования данные для подстановки вместо маркера хранятся в сессиях.
    16. Классам-детям даётся возможность изменить отцовскую логику обработки этих значений:
    17. */
    18.        $this->modify_session($mode);
    19.  
    20.     //Заменяем маркеры методов
    21.     $html=$this->blank_methods($html,$mode);
    22.  
    23.     //Заменяем маркеры свойств
    24.     $html=$this->blank_properties($html,$mode);
    25.  
    26.  
    27.     //Скореректируем путь к имиджам, которые ставит редактор tiny_mce
    28.     $html=preg_replace('/src="tiny_mce/','src="../../../../tiny_mce',$html);
    29.  
    30. //При формировании HTML-кода для редактирования иногда приходится "фиксировать" места для кнопок  
    31. //При печати мы убираем такие "гнёзда" для кнопок из HTML-кода шаблона
    32.  
    33.     if($mode==self::printer)
    34.         {
    35.         $html=preg_replace('/@@submit@@/','',$html);
    36.         $html=preg_replace('/@@anchor@@/','',$html);
    37.         }
    38.  
    39.     return $html;
    40.  
    41.     }
    PHP:
    1. //----------------  Заменяем маркеры методов  ----------------------------
    2. protected function blank_methods($html,$mode)
    3.     {
    4.     $html=$this->blank_methods_noedit($html);
    5.     $html=$this->blank_methods_edit($html,$mode);
    6.  
    7.     return $html;
    8.  
    9.     }
    PHP:
    1. //---------- Заменяем маркеры методов без поддержки редактирования ---------------------------------
    2. protected function blank_methods_noedit($html)
    3.     {
    4.     $re="/##(([a-z_]\w*)\(([^()]*)\))##/i";
    5.     preg_match_all($re,$html,$m,PREG_SET_ORDER);
    6.  
    7. /*
    8.     -==СОСТАВ МАССИВА $m==-
    9.  
    10.     перший індекс -- номер знайденої відповідності
    11.  
    12.     $m[i][0] -- полный текст маркера
    13.     $m[i][1] -- название метода с аргументами в скобках
    14.     $m[i][2] -- ім'я метода (без скобок)
    15.     $m[i][3] -- аргументы метода (без скобок)
    16. */
    17.    
    18.     for ($i=0;$i<count($m);$i++)
    19.         {
    20.         $eval="\$replacement=\$this->".$m[$i][1].";";
    21.         eval($eval);
    22.         $html=str_replace($m[$i][0],$replacement,$html);
    23.         }
    24.     return $html;
    25.     }
    PHP:
    1. //----------- Замена маркеров методов с поддержкой редактирования -----------------------------
    2. protected function blank_methods_edit($html,$mode)
    3.     {
    4.     $re="/%%(([a-z_]\w*)\(([^()]*)\))%%/i";
    5.     preg_match_all($re,$html,$m,PREG_SET_ORDER);
    6.  
    7. /*
    8.     -==СОСТАВ МАССИВА $m==-
    9.  
    10.     перший індекс -- номер знайденої відповідності
    11.  
    12.     $m[i][0] -- полный текст маркера
    13.     $m[i][1] -- название метода с аргументами в скобках
    14.     $m[i][2] -- ім'я метода (без скобок)
    15.     $m[i][3] -- аргументы метода (без скобок)
    16. */
    17.    
    18.     for ($i=0;$i<count($m);$i++)
    19.         {
    20.         $replacement=$this->blank_methods_edit_one($html,$mode,$m[$i][1]);
    21.        
    22.         $html=str_replace($m[$i][0],$replacement,$html);
    23.         }
    24.     return $html;
    25.     }
    PHP:
    1. //-------- HTML-код для замены одного маркера с поддержкой редакт-ия ----------------------------------
    2. protected function blank_methods_edit_one($html,$mode,$method)
    3.     {
    4.     $one='';
    5.     $default='';
    6.     $session=$this->method_session_index($method);
    7.     if(isset($_SESSION[$session]))
    8.         {
    9.         $default=$_SESSION[$session];
    10.         }
    11.     else
    12.         {
    13.         $eval="\$default=\$this->".$method.";";
    14.         eval($eval);
    15.         $default=$this->special_m_default($default,$method); // Чтоб дети могли подсуетиться с содержанием по умолчанию
    16.  
    17.         $_SESSION[$session]=$default;
    18.         }
    19.     switch ($mode)
    20.         {
    21.         case self::form:
    22.            
    23.  
    24.             $button="<input type="button" id="m_".preg_replace('/\(\)/','',$method).""  style="color:blue;background:yellow" value="Edit" onclick="
    25.             var url='http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['REQUEST_URI'])."/blank_edit.php?session=$session';   
    26.             w_blank=self.open(url,'w_blank','top=50,left=50');
    27.             if(w_blank != null)
    28.                 {
    29.                 w_blank.focus();
    30.                 }
    31.             " />";
    32.  
    33.             //Поищем "якорь" для кнопки
    34.             $re='/@@anchor@@/';
    35.             if(preg_match($re,$default))
    36.                 {
    37.                 $one=preg_replace($re,$button,$default);
    38.                 }
    39.             else
    40.                 {
    41.                 $one=$default.$button;
    42.                 }
    43.  
    44.             break;
    45.  
    46.         case self::printer:
    47.             $one=$default;
    48.             break;
    49.         }
    50.    
    51.     return $one;
    52.     }
     
  4. titch

    titch Активный пользователь

    С нами с:
    18 дек 2010
    Сообщения:
    847
    Симпатии:
    0
    Хм... а проект коммерческий?.. В смысле, вы кодом целиком не делитесь?...
     
  5. Villan

    Villan Активный пользователь

    С нами с:
    13 апр 2011
    Сообщения:
    36
    Симпатии:
    0
    Да я бы поделился - но у меня нет "автономного" кода этого проекта.

    Его нужно "с мясом" вырывать из своей поделки, писать комментарии (кстати, к представленному коду только что написал...), писать доку, примеры применения -- и всё равно останется много вопросов.

    Я проиллюстрировал только идею - которая, как я надеюсь, полезна тому, кто её оценит и реализует для себя. По-своему. А я бы помог ответами на много "мелочных" вопросов.
     
  6. Ensiferum

    Ensiferum Активный пользователь

    С нами с:
    11 июл 2010
    Сообщения:
    1.292
    Симпатии:
    0
    Адрес:
    из секты поклонников Нео
    А где-нибудь пощупать можно?