redmine

Added few services

@@ -2,12 +2,87 @@ @@ -2,12 +2,87 @@
2 2
3 require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Api/AbstractApi.php"; 3 require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Api/AbstractApi.php";
4 require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Api/SimpleXMLElement.php"; 4 require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Api/SimpleXMLElement.php";
  5 +require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Api/User.php";
5 require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Api/Issue.php"; 6 require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Api/Issue.php";
6 require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Api/Attachment.php"; 7 require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Api/Attachment.php";
7 require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Client.php"; 8 require_once "lib/3rdparty/php-redmine-api/lib/Redmine/Client.php";
8 9
9 require_once "config.php"; 10 require_once "config.php";
10 11
  12 +/*
  13 +
  14 +$user_redmine
  15 +
  16 +Array
  17 +(
  18 + [user] => Array
  19 + (
  20 + [id] => 17
  21 + [login] => AAAnikeyev
  22 + [firstname] => Артем
  23 + [lastname] => Аникеев
  24 + [mail] => AAAnikeyev@mephi.ru
  25 + [created_on] => 2014-03-05T06:25:14Z
  26 + [last_login_on] => 2014-07-17T11:10:01Z
  27 + [api_key] => xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  28 + [status] => 1
  29 + [custom_fields] => Array
  30 + (
  31 + [0] => Array
  32 + (
  33 + [id] => 19
  34 + [name] => Отчество
  35 + [value] => Андреевич
  36 + )
  37 +
  38 + )
  39 +
  40 + [groups] => Array
  41 + (
  42 + [0] => Array
  43 + (
  44 + [id] => 7
  45 + [name] => отдел юникс-технологий
  46 + )
  47 +
  48 + [1] => Array
  49 + (
  50 + [id] => 55
  51 + [name] => группа HPC
  52 + )
  53 +
  54 + )
  55 +
  56 + [memberships] => Array
  57 + (
  58 + [0] => Array
  59 + (
  60 + [id] => 777
  61 + [project] => Array
  62 + (
  63 + [id] => 102
  64 + [name] => *nix hosting request
  65 + )
  66 +
  67 + [roles] => Array
  68 + (
  69 + [0] => Array
  70 + (
  71 + [id] => 4
  72 + [name] => Разработчик
  73 + [inherited] => 1
  74 + )
  75 +
  76 + )
  77 +
  78 + )
  79 + )
  80 +
  81 + )
  82 +
  83 +)
  84 +*/
  85 +
11 function _tempdir_cleanup($dir) { 86 function _tempdir_cleanup($dir) {
12 # system('rm -rf "'.$dir.'"'); 87 # system('rm -rf "'.$dir.'"');
13 } 88 }
@@ -47,6 +122,9 @@ function body_parse($body) { @@ -47,6 +122,9 @@ function body_parse($body) {
47 return $body; 122 return $body;
48 } 123 }
49 124
  125 +$custom_fields = NULL;
  126 +
  127 +$custom_fields_keys = array();
50 switch ($_GET['file']) { 128 switch ($_GET['file']) {
51 case 'request/vpn': 129 case 'request/vpn':
52 $project_id = 1; 130 $project_id = 1;
@@ -57,21 +135,93 @@ switch ($_GET['file']) { @@ -57,21 +135,93 @@ switch ($_GET['file']) {
57 $memo_subject = 'Запрос на доступ к VLAN через vpn.mephi.ru'; 135 $memo_subject = 'Запрос на доступ к VLAN через vpn.mephi.ru';
58 break; 136 break;
59 case 'request/nix-hosting': 137 case 'request/nix-hosting':
60 - $project_id = 1; 138 + $project_id = 102;
61 $memo_subject = 'Заявка на предоставление nix-хостинга'; 139 $memo_subject = 'Заявка на предоставление nix-хостинга';
62 break; 140 break;
63 case 'request/win-hosting': 141 case 'request/win-hosting':
64 $project_id = 1; 142 $project_id = 1;
65 $memo_subject = 'Заявка на предоставление win-хостинга'; 143 $memo_subject = 'Заявка на предоставление win-хостинга';
66 break; 144 break;
  145 + case 'request/voip-softphone':
  146 + $project_id = 18;
  147 + $memo_subject = 'Заявка на создание учётной записи к softphone';
  148 + break;
  149 + case 'request/voip3':
  150 + $project_id = 124;
  151 + $memo_subject = 'Заявка на доступ к систему «Биллинг» IP-телефонии';
  152 + break;
  153 + case 'request/cps':
  154 + $project_id = 109;
  155 +// $project_id = 1;
  156 + $memo_subject = 'Заявка на доступ к системе учёта рабочего времени';
  157 + break;
67 case 'request/hpc': 158 case 'request/hpc':
68 - $project_id = NULL; //38; 159 +// $project_id = NULL; //38;
69 - $memo_subject = 'Запрос на учётную запись к vpn.mephi.ru'; 160 + $project_id = 38;
  161 + $memo_subject = 'Запрос на учётную запись к HPC-кластерам';
  162 +
  163 + $custom_fields_keys = array(2 => 'hdd-amount', 3 => 'cpu-amount', 4 => 'subdivision', 5 => 'scientific-director', 6 => 'ram-amount', 7 => 'preffered-login', 8 => 'ic-bandwidth', 16 => 'contact-email');
  164 + break;
  165 + case 'request/vacation':
  166 + $project_id = 118;
  167 + $memo_subject = 'Заявление на отпуск';
  168 +
  169 + switch($_GET['vacation-type']) {
  170 + case 'main':
  171 + $_GET['vacation-type'] = 'ежегодный основной оплачиваемый отпуск';
  172 + $_GET['of-vacation'] = 'ежегодного основного оплачиваемого отпуска';
  173 + break;
  174 + case 'educational':
  175 + $_GET['vacation-type'] = 'учебный отпуск';
  176 + $_GET['of-vacation'] = 'учебного отпуска';
  177 + break;
  178 + case 'free':
  179 + $_GET['vacation-type'] = 'отпуск без сохранения заработной платы';
  180 + $_GET['of-vacation'] = 'отпуска без сохранения заработной платы';
  181 + break;
  182 + case 'parental':
  183 + $_GET['vacation-type'] = 'отпуск по уходу за ребёнком до достижения им возраста трёх лет';
  184 + $_GET['of-vacation'] = 'отпуска по уходу за ребёнком до достижения им возраста трёх лет';
  185 + break;
  186 + }
  187 +
  188 + $time_from = strtotime($_GET['days-from']);
  189 + $time_to = strtotime($_GET['days-to']);
  190 +
  191 + $time_diff = $time_from - $time_to;
  192 +
  193 + $days_diff = floor(($time_diff / (3600*24)) + 0.5);
  194 +
  195 + $_GET['days-count'] = ($days_diff + 1);
  196 +
  197 + break;
  198 + case 'request/voip-transfer-equipment':
  199 + $project_id = 1;//18;
  200 + $memo_subject = 'Заявка на передачу телефонных аппаратов в ОСП';
70 break; 201 break;
71 default: 202 default:
72 die('unknown memo-type'); 203 die('unknown memo-type');
73 } 204 }
74 205
  206 +switch ($_GET['file']) {
  207 + case 'request/voip3':
  208 + case 'request/cps':
  209 + if (empty($_GET['subdiv-code'])) {
  210 + if (!empty($_SERVER['HTTP_REFERER'])) {
  211 + header('Location: '.$_SERVER['HTTP_REFERER'].'?errmsg='.urlencode('Не указан код подразделения'));
  212 + exit(0);
  213 + } else
  214 + die('"subdiv-code" is not set');
  215 + }
  216 + $subdivs = json_decode(file_get_contents('https://cps.mephi.ru/?cmd=getsubdivinfo&s_code='.$_GET['subdiv-code']));
  217 + $subdiv = $subdivs->result->s0;
  218 + $_GET['subdiv-name'] = $subdiv->name;
  219 + break;
  220 +}
  221 +
  222 +foreach($custom_fields_keys as $id => $key)
  223 + $custom_fields[] = array('id' => $id, 'value' => empty($_GET[$key]) ? '0' : $_GET[$key]);
  224 +
75 $tempdir = tempdir(); 225 $tempdir = tempdir();
76 226
77 if ($tempdir === FALSE) 227 if ($tempdir === FALSE)
@@ -80,62 +230,170 @@ if ($tempdir === FALSE) @@ -80,62 +230,170 @@ if ($tempdir === FALSE)
80 230
81 exec('cp -a /var/www/ut.mephi.ru/ut-tex/mephimemo "'.$tempdir.'/"'); 231 exec('cp -a /var/www/ut.mephi.ru/ut-tex/mephimemo "'.$tempdir.'/"');
82 chdir($tempdir.'/mephimemo'); 232 chdir($tempdir.'/mephimemo');
  233 +file_put_contents("request.get", print_r($_GET, true));
83 234
84 -ob_start(); 235 +#ob_start();
85 -print_r($_GET); 236 +#print_r($_GET);
86 -$_GET_print_r = ob_get_clean(); 237 +#$_GET_print_r = ob_get_clean();
87 - 238 +$text = '';
88 -$redmine = new Redmine\Client('https://redmine.ut.mephi.ru', REDMINE_LOGIN, REDMINE_PASSWORD);  
89 239
90 -if (!is_null($project_id)) { 240 +$redmine_admin = new Redmine\Client('https://redmine.ut.mephi.ru', REDMINE_LOGIN, REDMINE_PASSWORD);
91 - $issue = $redmine->api('issue')->create(  
92 - array(  
93 - 'project_id' => $project_id,  
94 - 'subject' => $memo_subject,  
95 - 'description' => $_GET_print_r,  
96 - )  
97 - );  
98 241
99 - $issue_id = $issue->id; 242 +/*
100 -} else { 243 +if (empty($_GET['date-end']))
101 - $issue_id = $_GET['issue-id'];  
102 -}  
103 -  
104 -if (!isset($_GET['date-end']))  
105 $_GET['date-end'] = (date('Y')+1).'-12-31'; 244 $_GET['date-end'] = (date('Y')+1).'-12-31';
  245 +*/
  246 +foreach (array('fullname' => 40, 'phonenumber' => 20, 'email' => 30, 'appointment' => 40, 'pgp-id' => 12) as $key => $space) {
  247 + if (empty($_GET['signer-'.$key]))
  248 + $_GET['signer-'.$key] = str_pad('', $space, '_');
106 249
107 -foreach (array('fullname', 'phonenumber', 'email') as $key) 250 + if (empty($_GET['user-'.$key]))
108 - if (!isset($_GET['contact-'.$key])) 251 + $_GET['user-'.$key] = str_pad('', $space, '_');
  252 +
  253 + if (empty($_GET['contact-'.$key]))
109 $_GET['contact-'.$key] = $_GET['user-'.$key]; 254 $_GET['contact-'.$key] = $_GET['user-'.$key];
  255 +}
110 256
111 -foreach ($_GET as $key => &$value) 257 +foreach (array('work-date-end' => 'Срок окончания работ') as $key => $descr) {
  258 + $_GET[$key.'-descr'] = $descr.': '.
  259 + (
  260 + isset($_GET['no-'.$key]) ?
  261 + 'Бессрочно' :
  262 + (isset ($_GET['work-date-end']) ?
  263 + $_GET['work-date-end'] :
  264 + '__.__.____'
  265 + )
  266 + ).'.';
  267 +}
  268 +foreach (array('ram-amount' => 'GB', 'hdd-amount' => 'GB', 'ic-bandwidth' => 'Gbps') as $key => $descr) {
  269 + $_GET[$key.'-descr'] = empty($_GET[$key]) ? '' : $_GET[$key].' '.$descr;
  270 +}
  271 +
  272 +foreach ($_GET as $key => &$value) {
  273 + if (substr($key, -12) == "-other-value")
  274 + if ($_GET[substr($key, 0, strlen($key)-12)] == "other")
  275 + $_GET[substr($key, 0, strlen($key)-12)] = $value;
112 $value = str_replace('_', '\_', $value); 276 $value = str_replace('_', '\_', $value);
  277 +}
  278 +
  279 +if (isset($_GET['user-serialized'])) {
  280 + $user_drupal_serialized = base64_decode($_GET['user-serialized']);
  281 + $hash = $_GET['user-signature'];
  282 + $good_signature = 0;
  283 + foreach ($SIGNKEYS as $key) {
  284 + if (sha1($user_drupal_serialized.$key) === $hash) {
  285 + $good_signature = 1;
  286 + break;
  287 + }
  288 + }
  289 + if ($good_signature == 0)
  290 + die('Bad signature');
  291 +
  292 + $user_drupal = unserialize($user_drupal_serialized);
  293 +
  294 + $user_redmine = NULL;
  295 + foreach ($redmine_admin->api('user')->all(array('name' => split('@', $user_drupal->user_id)[0]))['users'] as &$_user) {
  296 + if (strtolower($_user['login']).'@mephi.ru' == strtolower($user_drupal->user_id)) {
  297 + $user_redmine = $redmine_admin->api('user')->show($_user['id']);
  298 + break;
  299 + }
  300 + }
  301 +
  302 + if (is_null($user_redmine))
  303 + die('Cannot find user "'.$user_drupal->name.'" in Redmine');
  304 +
  305 +
  306 + $api_key = $user_redmine['user']['api_key'];
  307 +
  308 +// file_put_contents("/tmp/user", print_r($user_redmine)); die();
  309 + $redmine = new Redmine\Client('https://redmine.ut.mephi.ru', $api_key);
  310 +} else
  311 + $redmine = &$redmine_admin;
113 312
114 $body_template = file_get_contents('template/'.$_GET['file'].'.tex'); 313 $body_template = file_get_contents('template/'.$_GET['file'].'.tex');
115 $body = body_parse($body_template); 314 $body = body_parse($body_template);
116 315
117 -file_put_contents('header.tex', '\mmheader{Начальнику управления информатизации}{Н. Н. Романову}'); 316 +switch ($_GET['file']) {
  317 + case 'request/vacation':
  318 + $header = '\mmheader{Начальнику отдела кадров НИЯУ МИФИ}{}';
  319 + break;
  320 + case 'request/voip-transfer-equipment':
  321 + $header = '\mmfullheader{'.$_GET['subdiv-name'].'}{Начальнику управления информатизации}{Романову Н.Н.}';
  322 + break;
  323 + default:
  324 + $header = '\mmheader{Начальнику управления информатизации}{Н. Н. Романову}';
  325 +}
  326 +file_put_contents('header.tex', $header);
118 file_put_contents('body.tex', $body); 327 file_put_contents('body.tex', $body);
119 file_put_contents('footer.tex', '\mmfooter{'.$_GET['signer-appointment'].'}{'.$_GET{'signer-fullname'}.'}'); 328 file_put_contents('footer.tex', '\mmfooter{'.$_GET['signer-appointment'].'}{'.$_GET{'signer-fullname'}.'}');
120 -file_put_contents('responsible.tex', '\mmresponsible{'.$_GET['contact-fullname'].'}{'.$_GET{'contact-phonenumber'}.'}{'.$_GET['contact-email'].'}'); 329 +file_put_contents('responsible.tex', '\mmresponsibleskip');
  330 +
  331 +if (!is_null($project_id)) {
  332 + file_put_contents('urlqr.tex', '');
  333 + exec('make');
  334 + exec('pdftotext memo.pdf');
  335 +
  336 + $text = file_get_contents('memo.txt');
  337 + unlink('memo.pdf');
  338 +
  339 + $issue_props =
  340 + array(
  341 + 'project_id' => $project_id,
  342 + 'subject' => $memo_subject,
  343 + 'description' => $text,
  344 + );
  345 +
  346 + if (!is_null($custom_fields))
  347 + $issue_props['custom_fields'] = $custom_fields;
  348 +
  349 + $issue = $redmine->api('issue')->create($issue_props);
  350 +
  351 + $issue_id = $issue->id;
  352 +} else {
  353 + $issue_id = $_GET['issue-id'];
  354 +}
  355 +
121 file_put_contents('urlqr.tex', '\mmredmineurlqr{'.$issue_id.'}'); 356 file_put_contents('urlqr.tex', '\mmredmineurlqr{'.$issue_id.'}');
122 357
  358 +if (isset($user_redmine['user']['id']))
  359 + $redmine_admin->api('issue')->addWatcher($issue_id, $user_redmine['user']['id']);
  360 +
  361 +switch ($_GET['file']) {
  362 + case 'request/cps':
  363 + case 'request/voip3':
  364 + case 'request/voip-softphone':
  365 + $redmine_admin->api('issue')->addWatcher($issue_id, USERID_NNROMANOV);
  366 + $redmine_admin->api('issue')->addWatcher($issue_id, USERID_DYOKUNEV);
  367 + break;
  368 + case 'request/voip-transfer-equipment':
  369 + case 'request/vacation':
  370 + break;
  371 + default:
  372 + file_put_contents('responsible.tex', '\mmresponsible{'.$_GET['contact-fullname'].'}{'.$_GET{'contact-phonenumber'}.'}{'.$_GET['contact-email'].'}');
  373 +}
  374 +
123 exec('make'); 375 exec('make');
124 $pdf_content = file_get_contents('memo.pdf'); 376 $pdf_content = file_get_contents('memo.pdf');
125 377
126 -$pdf_upload = json_decode( $redmine->api('attachment')->upload($pdf_content) ); 378 +$pdf_upload = json_decode( $redmine_admin->api('attachment')->upload($pdf_content) );
127 379
128 -$redmine->api('issue')->attach( 380 +$redmine_admin->api('issue')->attach(
129 $issue_id, 381 $issue_id,
130 array( 382 array(
131 'token' => $pdf_upload->upload->token, 383 'token' => $pdf_upload->upload->token,
132 - 'filename' => 'memorandum.pdf', 384 + 'filename' => 'sluzhebnaya_zapiska.pdf',
133 - 'description' => 'Memorandum', 385 + 'description' => 'Служебная записка',
134 'content_type'=> 'application/pdf' 386 'content_type'=> 'application/pdf'
135 ) 387 )
136 ); 388 );
137 389
138 header('Content-type: application/pdf'); 390 header('Content-type: application/pdf');
139 -print $pdf_content; 391 +if (preg_match('/Firefox/i', $_SERVER['HTTP_USER_AGENT'])) {
  392 + system('convert -density 200 memo.pdf memo.png');
  393 + system('convert -density 200 memo.png memo_png.pdf');
  394 + print file_get_contents('memo_png.pdf');
  395 +} else {
  396 + print $pdf_content;
  397 +}
140 398
141 ?> 399 ?>
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 \usepackage{enumitem} % needed for example only 9 \usepackage{enumitem} % needed for example only
10 10
11 \begin{document} 11 \begin{document}
  12 +\begin{sloppypar}
12 \input{header.tex} 13 \input{header.tex}
13 14
14 \input{body.tex} 15 \input{body.tex}
@@ -16,5 +17,5 @@ @@ -16,5 +17,5 @@
16 \input{footer.tex} 17 \input{footer.tex}
17 \input{responsible.tex} 18 \input{responsible.tex}
18 \input{urlqr.tex} 19 \input{urlqr.tex}
19 - 20 +\end{sloppypar}
20 \end{document} 21 \end{document}
@@ -28,8 +28,56 @@ @@ -28,8 +28,56 @@
28 \usepackage{indentfirst} % indent first paragraph in section 28 \usepackage{indentfirst} % indent first paragraph in section
29 \usepackage{textcomp} % allow ligatures and special symbols 29 \usepackage{textcomp} % allow ligatures and special symbols
30 30
  31 +\usepackage[none]{hyphenat}
  32 +
31 \pagestyle{empty} 33 \pagestyle{empty}
32 34
  35 +% memorandum NRNU MEPhI header
  36 +\newcommand{\mmnrnumephi} {
  37 + \begin{center}
  38 + Министерство образования и науки Российской Федерации
  39 + \end{center}
  40 + \begin{center}
  41 + Федеральное государственное автономное образовательное учреждение высшего профессионального образования «Национальный исследовательский ядерный университет «МИФИ»
  42 + \end{center}
  43 +}
  44 +
  45 +% memorandum "from external subdivision"
  46 +% #1 - subdivision name
  47 +\newcommand{\mmorgfrom}[1] {
  48 + \begin{center}
  49 + {\bfseries {#1}}
  50 + \end{center}
  51 +}
  52 +
  53 +\newcommand{\mmstartmemo} {
  54 + \begin{center}
  55 + Служебная записка
  56 + \end{center}
  57 +}
  58 +
  59 +% memorandum recipient (while inter-organization communication)
  60 +% #1 - position
  61 +% #2 - name
  62 +\newcommand{\mmorgrecipient}[2]{
  63 + \hspace*{0.5\linewidth}
  64 + \begin{minipage}{0.5\linewidth}
  65 + \begin{flushleft}
  66 + {#1}\\
  67 + {#2}
  68 + \end{flushleft}
  69 + \end{minipage}
  70 +}
  71 +
  72 +\newcommand{\mmfullheader}[3] {
  73 + \mmnrnumephi
  74 + \mmorgfrom{{#1}}
  75 + \vspace{1em}
  76 + \mmorgrecipient{{#2}}{{#3}}
  77 + \vspace{1em}
  78 + \mmstartmemo
  79 +}
  80 +
33 % memorandum header 81 % memorandum header
34 % #1 - position 82 % #1 - position
35 % #2 - name 83 % #2 - name
@@ -40,9 +88,7 @@ @@ -40,9 +88,7 @@
40 \end{flushright} 88 \end{flushright}
41 89
42 \vspace{5em} 90 \vspace{5em}
43 - \begin{center} 91 + \mmstartmemo
44 - Служебная записка  
45 - \end{center}  
46 }