source: trunk/prototype/services/PostgreSQL.php @ 6299

Revision 6299, 12.7 KB checked in by acoutinho, 12 years ago (diff)

Ticket #2797 - Agendas sendo assinadas pelo proprio dono

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    }
202       
203    private static function parseUpdateData( $data , &$map){
204                                           
205            $d = array();
206            foreach ($data as $i => $v)
207            {
208                if(!isset($map[$i])) continue;
209               
210                $d[] = $map[$i].' = \''.addslashes ($v).'\'';
211            }
212           
213            return 'SET '.implode(',', $d);
214    }
215
216    private static function parseCriteria( $criteria  , &$map , $query = '' ){               
217       
218            if( isset($criteria["filter"]) && $criteria["filter"] !== NULL )
219            {
220                    /*
221                  * ex: array   (
222                  *               [0] 'OR',
223                  *               [1] array( 'OR', array( array( '=', 'campo', 'valor' ) ),
224                  *               [2] array( '=', 'campo' , 'valor' ),
225                  *               [3] array( 'IN', 'campo', array( '1' , '2' , '3' ) )
226                  *             )
227                  * OR
228                  *         array( '=' , 'campo' , 'valor' )
229                */
230                $query .= ($query === '') ?  'WHERE ('.self::parseFilter( $criteria['filter'] , $map).')' : ' AND ('.self::parseFilter( $criteria['filter'] , $map).')';
231            }
232            /*
233              * ex: array( 'table1' => 'table2' ,  'table1' => 'table2')
234              *         
235              */
236            if( isset($criteria["join"]) )
237            {
238                foreach ($criteria["join"] as $i => $v)
239                    $query .= ' AND '.$i.' = '.$v.' ';
240            }
241           
242            if( isset($criteria["group"]) )
243            {
244                    $query .= ' GROUP BY '.( is_array($criteria["group"]) ? implode(', ', $criteria["group"]) : $criteria["group"] ).' ';
245            }
246           
247            if( isset($criteria["order"]) )
248            {
249                    $query .= ' ORDER BY '.self::parseOrder( $criteria["order"], $map ).' ';
250            }
251            if( isset($criteria["limit"]) )
252            {
253                    $query .= ' LIMIT '. $criteria["limit"] .' ';
254            }
255            if( isset($criteria["offset"]) )
256            {
257                    $query .= ' OFFSET '. $criteria["offset"] .' ';
258            }
259           
260            return $query;
261    }
262   
263    private static function parseFilter( $filter ,&$map){
264   
265        if( !is_array( $filter ) || count($filter) <= 0) return null;
266               
267        $op = self::parseOperator( array_shift( $filter ) );
268       
269        if( is_array($filter[0]) )
270        {
271            $nested = array();
272
273            foreach( $filter as $i => $f )
274                if( $n = self::parseFilter( $f , $map))
275                    $nested[] = $n;
276
277               
278            return (count($nested) > 0 ) ? '('.implode( ' '.$op.' ', $nested ).')' : '';
279        }
280
281        if(!isset($map[$filter[0]])) return '';
282                 
283        $filter[0] = $map[$filter[0]];
284       
285        $igSuffix = $igPrefix = '';
286               
287        if( strpos( $op[0], 'i' ) === 0 )
288        {
289            $op[0] = substr( $op[0], 1 );
290            $filter[0] = 'upper("'.$filter[0].'")';
291            $igPrefix = 'upper(';
292            $igSuffix = ')';
293        }
294
295        if( is_array($filter[1]) )
296            return( $filter[0].' '.$op[0]." ($igPrefix'".implode( "'$igSuffix,$igPrefix'", array_map("addslashes" , $filter[1]) )."'$igSuffix)" );
297
298        return( $filter[0].' '.$op[0]." $igPrefix'".$op[1].addslashes( $filter[1] ).$op[2]."'$igSuffix" );
299    }
300
301    private static function parseOperator( $op ){
302   
303        switch(strtolower($op))
304        {
305            case 'and':
306            case 'or': return( $op );
307            case 'in': return array( $op );
308            case '!in': return array( 'NOT IN' );
309            case '^': return array( 'like', '%',  '' );
310            case '$': return array( 'like',  '', '%' );
311            case '*': return array( 'like', '%', '%' );
312            case 'i^': return array( 'ilike', '%',  '' );
313            case 'i$': return array( 'ilike',  '', '%' );
314            case 'i*': return array( 'ilike', '%', '%' );
315            default : return array( $op,  '',  '' );
316        }
317    }
318   
319    private static function parseJustthese($justthese , &$map)
320    {
321                 
322        if(!is_array($justthese)) //Caso seja um full select pegar todas as keys
323            $justthese = array_keys($map);
324
325        $return = array();
326
327        foreach ($justthese as &$value)
328        {
329            if(!isset($map[$value])) continue; //Escapa itens não existentes no mapa
330
331            if(is_array($map[$value]))
332                $return['deepness'][$value] = $map[$value];
333            else
334                $return['select'][] = $map[$value] .' as "'. $value. '"';
335        }
336       
337        $return['select'] = implode(', ', $return['select']);
338        return $return; 
339    }
340
341   private static function parseOrder($order , &$map)
342    {
343                 
344        if($notArray = !is_array($order)) //Caso seja um full select pegar todas as keys
345            $order = array( $order );
346
347        $return = array();
348
349        foreach ($order as &$value)
350        {
351            if(!isset($map[$value])) continue; //Escapa itens não existentes no mapa
352
353            $value = $map[$value];
354        }
355
356        return ( $notArray ?  $order[0] : implode(', ', $order) );
357    }
358}
359
360?>
Note: See TracBrowser for help on using the repository browser.