source: sandbox/2.4.1-3/prototype/services/PostgreSQL.php @ 6351

Revision 6351, 12.4 KB checked in by gustavo, 12 years ago (diff)

Ticket #2768 - Melhorias na inserção de destinatários na criacao de mensagem

Line 
1<?php
2/**
3 *
4 * Copyright (C) 2012 Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
5 *
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Affero General Public License version 3 as published by
8 * the Free Software Foundation with the addition of the following permission
9 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
10 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
11 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
16 * details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program; if not, see www.gnu.org/licenses or write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 * MA 02110-1301 USA.
22 *
23 * This code is based on the OpenXchange Connector and on the Prognus pSync
24 * Connector both developed by the community and licensed under the GPL
25 * version 2 or above as published by the Free Software Foundation.
26 *
27 * You can contact Prognus Software Livre headquarters at Av. Tancredo Neves,
28 * 6731, PTI, Edifício do Saber, 3º floor, room 306, Foz do Iguaçu - PR - Brasil or at
29 * e-mail address prognus@prognus.com.br.
30 *
31 * Classe de abstração que implementa métodos de manipulação de banco de dados
32 * executando instruções SQL a partir de parâmetros passados pelos métodos.
33 *
34 * @package    Prototype
35 * @license    http://www.gnu.org/copyleft/gpl.html GPL
36 * @author     Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br)
37 * @version    2.4
38 * @sponsor    Caixa Econômica Federal
39 * @since      Arquivo disponibilizado na versão 2.4
40 */
41
42class PostgreSQL implements Service
43{
44    private $con; //Conexão com o banco de dados
45    private $config; //Configuração
46    public  $error = false; //Armazena um erro caso ocorra
47   
48    public function find ( $uri, $justthese = false, $criteria = false ){
49                   
50        $map =  Config::get($uri['concept'], 'PostgreSQL.mapping');
51       
52        $criteria = ($criteria !== false) ? $this->parseCriteria ( $criteria , $map) : '';
53
54        $justthese = self::parseJustthese($justthese, $map);
55
56        return $this->execSql( 'SELECT '.$justthese['select'].' FROM '. (Config::get($uri['concept'],'PostgreSQL.concept')) .' '.$criteria );
57    }
58
59   public function read ( $uri, $justthese = false , $criteria = false){
60   
61      $map =  Config::get($uri['concept'], 'PostgreSQL.mapping');   
62      $justthese = self::parseJustthese($justthese, $map);
63      $criteria = ($criteria !== false) ? $this->parseCriteria ( $criteria , $map , ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'') : ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'';
64   
65      return $this->execSql( 'SELECT '.$justthese['select'].' FROM '. (Config::get($uri['concept'],'PostgreSQL.concept')) .$criteria , true );
66    }
67       
68    public function deleteAll ( $uri,   $justthese = false, $criteria = false ){
69            $map = Config::get($uri['concept'], 'PostgreSQL.mapping');
70            if(!self::parseCriteria ( $criteria , $map)) return false; //Validador para não apagar tabela inteira
71            return $this->execSql( 'DELETE FROM '.(Config::get($uri['concept'],'PostgreSQL.concept')).' '.self::parseCriteria ( $criteria ,$map) );
72    }
73
74    public function delete ( $uri, $justthese = false, $criteria = false ){
75            if(!isset($uri['id']) && !is_int($uri['id'])) return false; //Delete chamado apenas passando id inteiros
76            $map = Config::get($uri['concept'], 'PostgreSQL.mapping');
77            $criteria = ($criteria !== false) ? $this->parseCriteria ( $criteria , $map , ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'') : ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'';
78            return $this->execSql('DELETE FROM '.(Config::get($uri['concept'],'PostgreSQL.concept')).$criteria);
79    }
80
81    public function replace ( $uri,  $data, $criteria = false ){
82            $map = Config::get($uri['concept'], 'PostgreSQL.mapping');
83            return $this->execSql('UPDATE '.(Config::get($uri['concept'],'PostgreSQL.concept')).' '. self::parseUpdateData( $data ,$map).' '.self::parseCriteria($criteria , $map));
84    }
85               
86    public function update ( $uri,  $data, $criteria = false ){
87            $map = Config::get($uri['concept'], 'PostgreSQL.mapping');
88            $criteria = ($criteria !== false) ? $this->parseCriteria ( $criteria , $map , ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'') : ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'';
89            return $this->execSql('UPDATE '.(Config::get($uri['concept'],'PostgreSQL.concept')).' '. self::parseUpdateData( $data ,$map).$criteria);
90    }
91
92    public function create ( $uri,  $data ){   
93            return $this->execSql( 'INSERT INTO '.(Config::get($uri['concept'],'PostgreSQL.concept')).' '.self::parseInsertData( $data , $uri['concept'] ), true );
94    }
95
96    public function execSql( $sql, $unique = false )
97    {
98            if(!$this->con) $this->open( $this->config );
99
100            $rs = pg_query( $this->con, $sql );
101
102            switch( pg_num_rows( $rs ) )
103            {
104                case -1:
105                  $this->error = pg_last_error ( $this->con );
106                  return( false );
107
108                case 0:
109                  return( pg_affected_rows( $rs ) ? true : array() );
110
111                default:
112                  $return = array();
113
114                  while( $row = pg_fetch_assoc( $rs ) )
115                      $return[] = $row;
116
117                  return( $unique ? $return[0] : $return );
118            }
119    }
120
121
122    //@DEPRECATED
123    public function execResultSql( $sql, $unique = false ){
124            return $this->execSql( $sql, $unique );
125    }
126
127    public function begin( $uri ) {
128   
129        if(!$this->con)
130            $this->open( $this->config );
131       
132        $this->error = false;
133        pg_query($this->con, "BEGIN WORK");
134    }
135
136    public function commit($uri ) {
137   
138        if( $this->error !== false )
139        {
140            $error = $this->error;
141            $this->error = false;
142
143            throw new Exception( $error );
144        }
145
146        pg_query($this->con, "COMMIT");
147
148        return( true );
149    }
150
151    public function rollback( $uri ){
152   
153        pg_query($this->con, "ROLLBACK");
154    }
155
156    public function open  ( $config ){
157                       
158        $this->config = $config;
159       
160        $rs = '';
161        $rs .= ( isset($this->config['host']) && $this->config['host'] )  ? ' host='.$this->config['host'] : '' ;
162        $rs .= ( isset($this->config['user']) && $this->config['user'] )  ? ' user='.$this->config['user'] : '' ;
163        $rs .= ( isset($this->config['password']) && $this->config['password'] )  ? ' password='.$this->config['password'] : '' ;
164        $rs .= ( isset($this->config['dbname']) && $this->config['dbname'] )  ? ' dbname='.$this->config['dbname'] : '' ;
165        $rs .= ( isset($this->config['port']) && $this->config['port'] )  ? ' port='.$this->config['port'] : '' ;
166
167        if($this->con = pg_connect( $rs ))
168            return $this->con;
169
170        throw new Exception('It was not possible to enable the target connection!');
171        //$this->con = pg_connect('host='.$config['host'].' user='.$config['user'].' password='.$config['password'].' dbname='.$config['dbname'].'  options=\'--client_encoding=UTF8\'');
172    }
173
174    public function close(){
175
176            pg_close($this->con);
177           
178            $this->con = false;
179
180    }
181
182    public function setup(){}
183
184    public function teardown(){}
185
186    private static function parseInsertData( $data , $concept){
187         
188            $map = Config::get($concept, 'PostgreSQL.mapping');
189       
190            $ind = array();
191            $val = array();
192           
193            foreach ($data as $i => $v){
194                    if(!isset($map[$i])) continue;
195               
196                    $ind[] = $map[$i];
197                    $val[] = '\''.addslashes($v).'\'';
198            }
199
200//          return '('.implode(',', $ind).') VALUES ('.implode(',', $val).') RETURNING '.$map['id'].' as id';       
201            return '('.implode(',', $ind).') VALUES ('.implode(',', $val).') RETURNING id';         
202    }
203       
204    private static function parseUpdateData( $data , &$map){
205                                           
206            $d = array();
207            foreach ($data as $i => $v)
208            {
209                if(!isset($map[$i])) continue;
210               
211                $d[] = $map[$i].' = \''.addslashes ($v).'\'';
212            }
213           
214            return 'SET '.implode(',', $d);
215    }
216
217    private static function parseCriteria( $criteria  , &$map , $query = '' ){               
218       
219            if( isset($criteria["filter"]) && $criteria["filter"] !== NULL )
220            {
221                    /*
222                  * ex: array   (
223                  *               [0] 'OR',
224                  *               [1] array( 'OR', array( array( '=', 'campo', 'valor' ) ),
225                  *               [2] array( '=', 'campo' , 'valor' ),
226                  *               [3] array( 'IN', 'campo', array( '1' , '2' , '3' ) )
227                  *             )
228                  * OR
229                  *         array( '=' , 'campo' , 'valor' )
230                */
231                $query .= ($query === '') ?  'WHERE ('.self::parseFilter( $criteria['filter'] , $map).')' : ' AND ('.self::parseFilter( $criteria['filter'] , $map).')';
232            }
233            /*
234              * ex: array( 'table1' => 'table2' ,  'table1' => 'table2')
235              *         
236              */
237            if( isset($criteria["join"]) )
238            {
239                foreach ($criteria["join"] as $i => $v)
240                    $query .= ' AND '.$i.' = '.$v.' ';
241            }
242           
243            if( isset($criteria["group"]) )
244            {
245                    $query .= ' GROUP BY '.( is_array($criteria["group"]) ? implode(', ', $criteria["group"]) : $criteria["group"] ).' ';
246            }
247           
248            if( isset($criteria["order"]) )
249            {
250                    $query .= ' ORDER BY '.self::parseOrder( $criteria["order"], $map ).' ';
251            }
252            if( isset($criteria["limit"]) )
253            {
254                    $query .= ' LIMIT '. $criteria["limit"] .' ';
255            }
256            if( isset($criteria["offset"]) )
257            {
258                    $query .= ' OFFSET '. $criteria["offset"] .' ';
259            }
260           
261            return $query;
262    }
263   
264    private static function parseFilter( $filter ,&$map){
265   
266        if( !is_array( $filter ) || count($filter) <= 0) return null;
267               
268        $op = self::parseOperator( array_shift( $filter ) );
269       
270        if( is_array($filter[0]) )
271        {
272            $nested = array();
273
274            foreach( $filter as $i => $f )
275                if( $n = self::parseFilter( $f , $map))
276                    $nested[] = $n;
277
278               
279            return (count($nested) > 0 ) ? '('.implode( ' '.$op.' ', $nested ).')' : '';
280        }
281
282        if(!isset($map[$filter[0]])) return '';
283                 
284        $filter[0] = $map[$filter[0]];
285       
286        $igSuffix = $igPrefix = '';
287               
288        if( strpos( $op[0], 'i' ) === 0 )
289        {
290            $op[0] = substr( $op[0], 1 );
291            $filter[0] = 'upper("'.$filter[0].'")';
292            $igPrefix = 'upper(';
293            $igSuffix = ')';
294        }
295
296        if( is_array($filter[1]) )
297            return( $filter[0].' '.$op[0]." ($igPrefix'".implode( "'$igSuffix,$igPrefix'", array_map("addslashes" , $filter[1]) )."'$igSuffix)" );
298
299        return( $filter[0].' '.$op[0]." $igPrefix'".$op[1].addslashes( $filter[1] ).$op[2]."'$igSuffix" );
300    }
301
302    private static function parseOperator( $op ){
303   
304        switch(strtolower($op))
305        {
306            case 'and':
307            case 'or': return( $op );
308            case 'in': return array( $op );
309            case '!in': return array( 'NOT IN' );
310            case '^': return array( 'like', '%',  '' );
311            case '$': return array( 'like',  '', '%' );
312            case '*': return array( 'like', '%', '%' );
313            case 'i^': return array( 'ilike', '%',  '' );
314            case 'i$': return array( 'ilike',  '', '%' );
315            case 'i*': return array( 'ilike', '%', '%' );
316            default : return array( $op,  '',  '' );
317        }
318    }
319   
320    private static function parseJustthese($justthese , &$map)
321    {
322                 
323        if(!is_array($justthese)) //Caso seja um full select pegar todas as keys
324            $justthese = array_keys($map);
325
326        $return = array();
327
328        foreach ($justthese as &$value)
329        {
330            if(!isset($map[$value])) continue; //Escapa itens não existentes no mapa
331
332            if(is_array($map[$value]))
333                $return['deepness'][$value] = $map[$value];
334            else
335                $return['select'][] = $map[$value] .' as "'. $value. '"';
336        }
337       
338        $return['select'] = implode(', ', $return['select']);
339        return $return; 
340    }
341
342   private static function parseOrder($order , &$map)
343    {
344                 
345        if($notArray = !is_array($order)) //Caso seja um full select pegar todas as keys
346            $order = array( $order );
347
348        $return = array();
349
350        foreach ($order as &$value)
351        {
352            if(!isset($map[$value])) continue; //Escapa itens não existentes no mapa
353
354            $value = $map[$value];
355        }
356
357        return ( $notArray ?  $order[0] : implode(', ', $order) );
358    }
359}
360
361?>
Note: See TracBrowser for help on using the repository browser.