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

Revision 6357, 12.5 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
42use prototype\api\Config as Config;
43
44class PostgreSQL implements Service
45{
46    private $con; //Conexão com o banco de dados
47    private $config; //Configuração
48    public  $error = false; //Armazena um erro caso ocorra
49   
50    public function find ( $uri, $justthese = false, $criteria = false ){
51                   
52        $map =  Config::get($uri['concept'], 'PostgreSQL.mapping');
53       
54        $criteria = ($criteria !== false) ? $this->parseCriteria ( $criteria , $map) : '';
55
56        $justthese = self::parseJustthese($justthese, $map);
57
58        return $this->execSql( 'SELECT '.$justthese['select'].' FROM '. (Config::get($uri['concept'],'PostgreSQL.concept')) .' '.$criteria );
59    }
60
61   public function read ( $uri, $justthese = false , $criteria = false){
62   
63      $map =  Config::get($uri['concept'], 'PostgreSQL.mapping');   
64      $justthese = self::parseJustthese($justthese, $map);
65      $criteria = ($criteria !== false) ? $this->parseCriteria ( $criteria , $map , ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'') : ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'';
66   
67      return $this->execSql( 'SELECT '.$justthese['select'].' FROM '. (Config::get($uri['concept'],'PostgreSQL.concept')) .$criteria , true );
68    }
69       
70    public function deleteAll ( $uri,   $justthese = false, $criteria = false ){
71            $map = Config::get($uri['concept'], 'PostgreSQL.mapping');
72            if(!self::parseCriteria ( $criteria , $map)) return false; //Validador para não apagar tabela inteira
73            return $this->execSql( 'DELETE FROM '.(Config::get($uri['concept'],'PostgreSQL.concept')).' '.self::parseCriteria ( $criteria ,$map) );
74    }
75
76    public function delete ( $uri, $justthese = false, $criteria = false ){
77            if(!isset($uri['id']) && !is_int($uri['id'])) return false; //Delete chamado apenas passando id inteiros
78            $map = Config::get($uri['concept'], 'PostgreSQL.mapping');
79            $criteria = ($criteria !== false) ? $this->parseCriteria ( $criteria , $map , ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'') : ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'';
80            return $this->execSql('DELETE FROM '.(Config::get($uri['concept'],'PostgreSQL.concept')).$criteria);
81    }
82
83    public function replace ( $uri,  $data, $criteria = false ){
84            $map = Config::get($uri['concept'], 'PostgreSQL.mapping');
85            return $this->execSql('UPDATE '.(Config::get($uri['concept'],'PostgreSQL.concept')).' '. self::parseUpdateData( $data ,$map).' '.self::parseCriteria($criteria , $map));
86    }
87               
88    public function update ( $uri,  $data, $criteria = false ){
89            $map = Config::get($uri['concept'], 'PostgreSQL.mapping');
90            $criteria = ($criteria !== false) ? $this->parseCriteria ( $criteria , $map , ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'') : ' WHERE '.$map['id'].' = \''.addslashes( $uri['id'] ).'\'';
91            return $this->execSql('UPDATE '.(Config::get($uri['concept'],'PostgreSQL.concept')).' '. self::parseUpdateData( $data ,$map).$criteria);
92    }
93
94    public function create ( $uri,  $data ){   
95            return $this->execSql( 'INSERT INTO '.(Config::get($uri['concept'],'PostgreSQL.concept')).' '.self::parseInsertData( $data , $uri['concept'] ), true );
96    }
97
98    public function execSql( $sql, $unique = false )
99    {
100            if(!$this->con) $this->open( $this->config );
101
102            $rs = pg_query( $this->con, $sql );
103
104            switch( pg_num_rows( $rs ) )
105            {
106                case -1:
107                  $this->error = pg_last_error ( $this->con );
108                  return( false );
109
110                case 0:
111                  return( pg_affected_rows( $rs ) ? true : array() );
112
113                default:
114                  $return = array();
115
116                  while( $row = pg_fetch_assoc( $rs ) )
117                      $return[] = $row;
118
119                  return( $unique ? $return[0] : $return );
120            }
121    }
122
123
124    //@DEPRECATED
125    public function execResultSql( $sql, $unique = false ){
126            return $this->execSql( $sql, $unique );
127    }
128
129    public function begin( $uri ) {
130   
131        if(!$this->con)
132            $this->open( $this->config );
133       
134        $this->error = false;
135        pg_query($this->con, "BEGIN WORK");
136    }
137
138    public function commit($uri ) {
139   
140        if( $this->error !== false )
141        {
142            $error = $this->error;
143            $this->error = false;
144
145            throw new Exception( $error );
146        }
147
148        pg_query($this->con, "COMMIT");
149
150        return( true );
151    }
152
153    public function rollback( $uri ){
154   
155        pg_query($this->con, "ROLLBACK");
156    }
157
158    public function open  ( $config ){
159                       
160        $this->config = $config;
161       
162        $rs = '';
163        $rs .= ( isset($this->config['host']) && $this->config['host'] )  ? ' host='.$this->config['host'] : '' ;
164        $rs .= ( isset($this->config['user']) && $this->config['user'] )  ? ' user='.$this->config['user'] : '' ;
165        $rs .= ( isset($this->config['password']) && $this->config['password'] )  ? ' password='.$this->config['password'] : '' ;
166        $rs .= ( isset($this->config['dbname']) && $this->config['dbname'] )  ? ' dbname='.$this->config['dbname'] : '' ;
167        $rs .= ( isset($this->config['port']) && $this->config['port'] )  ? ' port='.$this->config['port'] : '' ;
168
169        if($this->con = pg_connect( $rs ))
170            return $this->con;
171
172        throw new Exception('It was not possible to enable the target connection!');
173        //$this->con = pg_connect('host='.$config['host'].' user='.$config['user'].' password='.$config['password'].' dbname='.$config['dbname'].'  options=\'--client_encoding=UTF8\'');
174    }
175
176    public function close(){
177
178            pg_close($this->con);
179           
180            $this->con = false;
181
182    }
183
184    public function setup(){}
185
186    public function teardown(){}
187
188    private static function parseInsertData( $data , $concept){
189         
190            $map = Config::get($concept, 'PostgreSQL.mapping');
191       
192            $ind = array();
193            $val = array();
194           
195            foreach ($data as $i => $v){
196                    if(!isset($map[$i])) continue;
197               
198                    $ind[] = $map[$i];
199                    $val[] = '\''.addslashes($v).'\'';
200            }
201
202//          return '('.implode(',', $ind).') VALUES ('.implode(',', $val).') RETURNING '.$map['id'].' as id';       
203            return '('.implode(',', $ind).') VALUES ('.implode(',', $val).') RETURNING id';         
204    }
205       
206    private static function parseUpdateData( $data , &$map){
207                                           
208            $d = array();
209            foreach ($data as $i => $v)
210            {
211                if(!isset($map[$i])) continue;
212               
213                $d[] = $map[$i].' = \''.addslashes ($v).'\'';
214            }
215           
216            return 'SET '.implode(',', $d);
217    }
218
219    private static function parseCriteria( $criteria  , &$map , $query = '' ){               
220       
221            if( isset($criteria["filter"]) && $criteria["filter"] !== NULL )
222            {
223                    /*
224                  * ex: array   (
225                  *               [0] 'OR',
226                  *               [1] array( 'OR', array( array( '=', 'campo', 'valor' ) ),
227                  *               [2] array( '=', 'campo' , 'valor' ),
228                  *               [3] array( 'IN', 'campo', array( '1' , '2' , '3' ) )
229                  *             )
230                  * OR
231                  *         array( '=' , 'campo' , 'valor' )
232                */
233                $query .= ($query === '') ?  'WHERE ('.self::parseFilter( $criteria['filter'] , $map).')' : ' AND ('.self::parseFilter( $criteria['filter'] , $map).')';
234            }
235            /*
236              * ex: array( 'table1' => 'table2' ,  'table1' => 'table2')
237              *         
238              */
239            if( isset($criteria["join"]) )
240            {
241                foreach ($criteria["join"] as $i => $v)
242                    $query .= ' AND '.$i.' = '.$v.' ';
243            }
244           
245            if( isset($criteria["group"]) )
246            {
247                    $query .= ' GROUP BY '.( is_array($criteria["group"]) ? implode(', ', $criteria["group"]) : $criteria["group"] ).' ';
248            }
249           
250            if( isset($criteria["order"]) )
251            {
252                    $query .= ' ORDER BY '.self::parseOrder( $criteria["order"], $map ).' ';
253            }
254            if( isset($criteria["limit"]) )
255            {
256                    $query .= ' LIMIT '. $criteria["limit"] .' ';
257            }
258            if( isset($criteria["offset"]) )
259            {
260                    $query .= ' OFFSET '. $criteria["offset"] .' ';
261            }
262           
263            return $query;
264    }
265   
266    private static function parseFilter( $filter ,&$map){
267   
268        if( !is_array( $filter ) || count($filter) <= 0) return null;
269               
270        $op = self::parseOperator( array_shift( $filter ) );
271       
272        if( is_array($filter[0]) )
273        {
274            $nested = array();
275
276            foreach( $filter as $i => $f )
277                if( $n = self::parseFilter( $f , $map))
278                    $nested[] = $n;
279
280               
281            return (count($nested) > 0 ) ? '('.implode( ' '.$op.' ', $nested ).')' : '';
282        }
283
284        if(!isset($map[$filter[0]])) return '';
285                 
286        $filter[0] = $map[$filter[0]];
287       
288        $igSuffix = $igPrefix = '';
289               
290        if( strpos( $op[0], 'i' ) === 0 )
291        {
292            $op[0] = substr( $op[0], 1 );
293            $filter[0] = 'upper("'.$filter[0].'")';
294            $igPrefix = 'upper(';
295            $igSuffix = ')';
296        }
297
298        if( is_array($filter[1]) )
299            return( $filter[0].' '.$op[0]." ($igPrefix'".implode( "'$igSuffix,$igPrefix'", array_map("addslashes" , $filter[1]) )."'$igSuffix)" );
300
301        return( $filter[0].' '.$op[0]." $igPrefix'".$op[1].addslashes( $filter[1] ).$op[2]."'$igSuffix" );
302    }
303
304    private static function parseOperator( $op ){
305   
306        switch(strtolower($op))
307        {
308            case 'and':
309            case 'or': return( $op );
310            case 'in': return array( $op );
311            case '!in': return array( 'NOT IN' );
312            case '^': return array( 'like', '%',  '' );
313            case '$': return array( 'like',  '', '%' );
314            case '*': return array( 'like', '%', '%' );
315            case 'i^': return array( 'ilike', '%',  '' );
316            case 'i$': return array( 'ilike',  '', '%' );
317            case 'i*': return array( 'ilike', '%', '%' );
318            default : return array( $op,  '',  '' );
319        }
320    }
321   
322    private static function parseJustthese($justthese , &$map)
323    {
324                 
325        if(!is_array($justthese)) //Caso seja um full select pegar todas as keys
326            $justthese = array_keys($map);
327
328        $return = array();
329
330        foreach ($justthese as &$value)
331        {
332            if(!isset($map[$value])) continue; //Escapa itens não existentes no mapa
333
334            if(is_array($map[$value]))
335                $return['deepness'][$value] = $map[$value];
336            else
337                $return['select'][] = $map[$value] .' as "'. $value. '"';
338        }
339       
340        $return['select'] = implode(', ', $return['select']);
341        return $return; 
342    }
343
344   private static function parseOrder($order , &$map)
345    {
346                 
347        if($notArray = !is_array($order)) //Caso seja um full select pegar todas as keys
348            $order = array( $order );
349
350        $return = array();
351
352        foreach ($order as &$value)
353        {
354            if(!isset($map[$value])) continue; //Escapa itens não existentes no mapa
355
356            $value = $map[$value];
357        }
358
359        return ( $notArray ?  $order[0] : implode(', ', $order) );
360    }
361}
362
363?>
Note: See TracBrowser for help on using the repository browser.