· 4 years ago · Apr 06, 2021, 08:42 PM
1<?php
2/**
3 * @copyright Copyright (c) 2008-2009 Quality Unit s.r.o.
4 * @author Quality Unit
5 * @package PapApi
6 * @since Version 1.0.0
7 *
8 * Licensed under the Quality Unit, s.r.o. Dual License Agreement,
9 * Version 1.0 (the "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 * http://www.qualityunit.com/licenses/gpf
12 * Generated on: 2021-03-25 09:57:28
13 * PAP version: 5.10.0.2, GPF version: 1.3.66.0
14 *
15 */
16
17namespace Qu\Pap\Api;
18
19use Exception;
20use stdClass;
21use Iterator;
22use IteratorAggregate;
23use ArrayIterator;
24
25define('PAP_API_VERSION', '1.0.0.2');
26
27if (!class_exists('Gpf', false)) {
28 class Gpf {
29 const YES = 'Y';
30 const NO = 'N';
31 }
32}
33
34if (!class_exists('Gpf_Object', false)) {
35 class Gpf_Object {
36 protected function createDatabase() {
37 return Gpf_DbEngine_Database::getDatabase();
38 }
39
40 public function _($message) {
41 return $message;
42 }
43
44 public function _localize($message) {
45 return $message;
46 }
47
48 public function _sys($message) {
49 return $message;
50 }
51 }
52}
53
54if (!interface_exists('Gpf_Rpc_Serializable', false)) {
55 interface Gpf_Rpc_Serializable {
56
57 public function toObject();
58
59 public function toText();
60 }
61
62} //end Gpf_Rpc_Serializable
63
64if (!interface_exists('Gpf_Rpc_DataEncoder', false)) {
65 interface Gpf_Rpc_DataEncoder {
66 function encodeResponse(Gpf_Rpc_Serializable $response);
67 }
68
69
70
71} //end Gpf_Rpc_DataEncoder
72
73if (!interface_exists('Gpf_Rpc_DataDecoder', false)) {
74 interface Gpf_Rpc_DataDecoder {
75 /**
76 * @param string $str
77 * @return StdClass
78 */
79 function decode($str);
80 }
81
82
83
84} //end Gpf_Rpc_DataDecoder
85
86if (!class_exists('Gpf_Rpc_Array', false)) {
87 class Gpf_Rpc_Array extends Gpf_Object implements Gpf_Rpc_Serializable, IteratorAggregate {
88
89
90 private $array;
91
92 function __construct(array $array = null){
93 if($array === null){
94 $this->array = array();
95 }else{
96 $this->array = $array;
97 }
98 }
99
100 public function add($response) {
101 if(is_scalar($response) || $response instanceof Gpf_Rpc_Serializable) {
102 $this->array[] = $response;
103 return;
104 }
105 throw new Gpf_Exception("Value of type " . gettype($response) . " is not scalar or Gpf_Rpc_Serializable");
106 }
107
108 public function toObject() {
109 $array = array();
110 foreach ($this->array as $response) {
111 if($response instanceof Gpf_Rpc_Serializable) {
112 $array[] = $response->toObject();
113 } else {
114 $array[] = $response;
115 }
116 }
117 return $array;
118 }
119
120 public function toText() {
121 return var_dump($this->array);
122 }
123
124 public function getCount() {
125 return count($this->array);
126 }
127
128 public function get($index) {
129 return $this->array[$index];
130 }
131
132 /**
133 *
134 * @return ArrayIterator
135 */
136 public function getIterator() {
137 return new ArrayIterator($this->array);
138 }
139 }
140
141} //end Gpf_Rpc_Array
142
143if (!class_exists('Gpf_Rpc_Server', false)) {
144 class Gpf_Rpc_Server extends Gpf_Object {
145 const REQUESTS = 'requests';
146 const REQUESTS_SHORT = 'R';
147 const RUN_METHOD = 'run';
148 const FORM_REQUEST = 'FormRequest';
149 const FORM_RESPONSE = 'FormResponse';
150 const BODY_DATA_NAME = 'D';
151
152
153 const HANDLER_FORM = 'Y';
154 const HANDLER_JASON = 'N';
155 const HANDLER_WINDOW_NAME = 'W';
156
157 /**
158 * @var Gpf_Rpc_DataEncoder
159 */
160 private $dataEncoder;
161 /**
162 * @var Gpf_Rpc_DataDecoder
163 */
164 private $dataDecoder;
165
166 private $isStripHtmlTags = false;
167
168 public function __construct() {
169 }
170
171 private function initDatabaseLogger() {
172 $logger = Gpf_Log_Logger::getInstance();
173
174 if(!$logger->checkLoggerTypeExists(Gpf_Log_LoggerDatabase::TYPE)) {
175 $logger->setGroup(Gpf_Common_String::generateId(10));
176 $logLevel = Gpf_Settings::get(Gpf_Settings_Gpf::LOG_LEVEL_SETTING_NAME);
177 $logger->add(Gpf_Log_LoggerDatabase::TYPE, $logLevel);
178 }
179 }
180
181 /**
182 * Return response to standard output
183 */
184 public function executeAndEcho($request = '') {
185 $response = $this->encodeResponse($this->execute($request));
186 if ($this->isStripHtmlTags) {
187 $response = strip_tags($response);
188 }
189 Gpf_ModuleBase::startGzip();
190 echo $response;
191 Gpf_ModuleBase::flushGzip();
192 }
193
194 /**
195 * @return Gpf_Rpc_Serializable
196 */
197 public function execute($request = '') {
198 try {
199 if(isset($_REQUEST[self::BODY_DATA_NAME])) {
200 $request = $_REQUEST[self::BODY_DATA_NAME];
201 }
202 if($this->isStandardRequestUsed($_REQUEST)) {
203 $request = $this->setStandardRequest();
204 }
205
206 $this->setDecoder($request);
207 $params = new Gpf_Rpc_Params($this->decodeRequest($request));
208 $this->setEncoder($params);
209 $response = $this->executeRequest($params);
210 } catch (Exception $e) {
211 return new Gpf_Rpc_ExceptionResponse($e);
212 }
213 if ($this->isFormRequest($request) && $response instanceof Gpf_Rpc_Form && $params->get(self::FORM_RESPONSE) != self::HANDLER_WINDOW_NAME) {
214 $this->isStripHtmlTags = true;
215 }
216 return $response;
217 }
218
219 /**
220 *
221 * @param unknown_type $requestObj
222 * @return Gpf_Rpc_Serializable
223 */
224 private function executeRequest(Gpf_Rpc_Params $params) {
225 try {
226 Gpf_Db_LoginHistory::logRequest();
227 return $this->callServiceMethod($params);
228 } catch (Gpf_Rpc_SessionExpiredException $e) {
229 return $e;
230 } catch (Exception $e) {
231 return new Gpf_Rpc_ExceptionResponse($e);
232 }
233 }
234
235 protected function callServiceMethod(Gpf_Rpc_Params $params) {
236 $method = new Gpf_Rpc_ServiceMethod($params);
237 return $method->invoke($params);
238 }
239
240 /**
241 * Compute correct handler type for server response
242 *
243 * @param array $requestData
244 * @param string $type
245 * @return string
246 */
247 private function getEncoderHandlerType($requestData) {
248 if ($this->isFormHandler($requestData, self::FORM_RESPONSE, self::HANDLER_FORM)) {
249 return self::HANDLER_FORM;
250 }
251 if ($this->isFormHandler($requestData, self::FORM_RESPONSE, self::HANDLER_WINDOW_NAME)) {
252 return self::HANDLER_WINDOW_NAME;
253 }
254 return self::HANDLER_JASON;
255 }
256
257
258 private function isFormHandler($requestData, $type, $handler) {
259 return (isset($_REQUEST[$type]) && $_REQUEST[$type] == $handler) ||
260 (isset($requestData) && isset($requestData[$type]) && $requestData[$type] == $handler);
261 }
262
263 private function decodeRequest($requestData) {
264 return $this->dataDecoder->decode($requestData);
265 }
266
267 private function isStandardRequestUsed($requestArray) {
268 return is_array($requestArray) && array_key_exists(Gpf_Rpc_Params::CLASS_NAME, $requestArray);
269 }
270
271 private function setStandardRequest() {
272 return array_merge($_POST, $_GET);
273 }
274
275 private function isFormRequest($request) {
276 return $this->isFormHandler($request, self::FORM_REQUEST, self::HANDLER_FORM);
277 }
278
279 private function encodeResponse(Gpf_Rpc_Serializable $response) {
280 return $this->dataEncoder->encodeResponse($response);
281 }
282
283
284 private function setDecoder($request) {
285 if ($this->isFormRequest($request)) {
286 Gpf_Http::setHeader('Content-Type', 'text/plain; charset=utf-8');
287 $this->dataDecoder = new Gpf_Rpc_FormHandler();
288 } else {
289 Gpf_Http::setHeader('Content-Type', 'application/json; charset=utf-8');
290 $this->dataDecoder = new Gpf_Rpc_Json();
291 }
292 }
293
294 private function setEncoder(Gpf_Rpc_Params $params) {
295 switch ($params->get(self::FORM_RESPONSE)) {
296 case self::HANDLER_FORM:
297 $this->dataEncoder = new Gpf_Rpc_FormHandler();
298 break;
299 case self::HANDLER_WINDOW_NAME:
300 $this->dataEncoder = new Gpf_Rpc_WindowNameHandler();
301 break;
302 default:
303 $this->dataEncoder = new Gpf_Rpc_Json();
304 break;
305 }
306 }
307
308 /**
309 * Executes multi request
310 *
311 * @service
312 * @anonym
313 * @return Gpf_Rpc_Serializable
314 */
315 public function run(Gpf_Rpc_Params $params) {
316 $response = new Gpf_Rpc_Array();
317 foreach ($this->getRequestsArray($params) as $request) {
318 $response->add($this->executeRequest(new Gpf_Rpc_Params($request)));
319 }
320 return $response;
321 }
322
323 public function getRequestsArray(Gpf_Rpc_Params $params) {
324 $requestArray = $params->get(self::REQUESTS);
325
326 if ($requestArray === null) {
327 $requestArray = $params->get(self::REQUESTS_SHORT);
328 }
329 return $requestArray;
330 }
331
332 /**
333 * Set time offset between client and server and store it to session
334 * Offset is computed as client time - server time
335 *
336 * @anonym
337 * @service
338 * @param Gpf_Rpc_Params $params
339 * @return Gpf_Rpc_Action
340 */
341 public function syncTime(Gpf_Rpc_Params $params) {
342 $action = new Gpf_Rpc_Action($params);
343 $timeOffset = $action->getParam('offset')/1000;
344 if (abs($timeOffset) > (24 * 60 * 60)) {
345 $timeOffset = $timeOffset % (24 * 60 * 60);
346 }
347 Gpf_Session::getInstance()->setTimeOffset($timeOffset);
348 $action->addOk();
349 return $action;
350 }
351 }
352
353} //end Gpf_Rpc_Server
354
355if (!class_exists('Gpf_Rpc_MultiRequest', false)) {
356 class Gpf_Rpc_MultiRequest extends Gpf_Object {
357 private $url = '';
358 private $useNewStyleRequestsEncoding;
359 private $maxTimeout;
360 /**
361 *
362 * @var Gpf_Rpc_Array
363 */
364 private $requests;
365 /**
366 * @var Gpf_Rpc_Json
367 */
368 private $json;
369 protected $serverClassName = 'Gpf_Rpc_Server';
370
371 private $sessionId = null;
372
373 private $debugRequests = false;
374
375 /**
376 * @var Gpf_Rpc_MultiRequest
377 */
378 private static $instance;
379
380 public function __construct() {
381 $this->json = new Gpf_Rpc_Json();
382 $this->requests = new Gpf_Rpc_Array();
383 }
384
385 public function useNewStyleRequestsEncoding($useNewStyle) {
386 $this->useNewStyleRequestsEncoding = $useNewStyle;
387 }
388
389 public function setMaxTimeout($timeout) {
390 $this->maxTimeout = $timeout;
391 }
392
393 /**
394 * @return Gpf_Rpc_MultiRequest
395 */
396 public static function getInstance() {
397 if(self::$instance === null) {
398 self::$instance = new Gpf_Rpc_MultiRequest();
399 }
400 return self::$instance;
401 }
402
403 public static function setInstance(Gpf_Rpc_MultiRequest $instance) {
404 self::$instance = $instance;
405 }
406
407 public function add(Gpf_Rpc_Request $request) {
408 $this->requests->add($request);
409 }
410
411 /**
412 * Should be used only in API
413 * @param $requestBody
414 * @return string
415 * @throws Gpf_Exception
416 */
417 protected function sendRequest($requestBody) {
418 $request = new Gpf_Net_Http_Request();
419
420 $request->setMethod('POST');
421 $request->setBody(Gpf_Rpc_Server::BODY_DATA_NAME . '=' . urlencode($requestBody));
422 $request->setUrl($this->url);
423 if ($this->maxTimeout != '') {
424 $request->setMaxTimeout($this->maxTimeout);
425 }
426
427 $client = new Gpf_Net_Http_Client();
428 $response = $client->execute($request);
429 if ($response->getResponseCode() == 429) {
430 throw new Gpf_Exception($this->_('Too Many Requests. Please try to send request later.'));
431 }
432 return $response->getBody();
433 }
434
435 public function setSessionId($sessionId) {
436 $this->sessionId = $sessionId;
437 }
438
439 public function setDebugRequests($debug) {
440 $this->debugRequests = $debug;
441 }
442
443 /**
444 * Should be used only in API
445 * @throws Gpf_Exception
446 * @throws Gpf_Rpc_ExecutionException
447 */
448 public function send() {
449 $request = new Gpf_Rpc_Request($this->serverClassName, Gpf_Rpc_Server::RUN_METHOD);
450 if ($this->useNewStyleRequestsEncoding) {
451 $request->addParam(Gpf_Rpc_Server::REQUESTS_SHORT, $this->requests);
452 } else {
453 $request->addParam(Gpf_Rpc_Server::REQUESTS, $this->requests);
454 }
455 if($this->sessionId != null) {
456 $request->addParam("S", $this->sessionId);
457 }
458 $requestBody = $this->json->encodeResponse($request);
459 $responseText = $this->sendRequest($requestBody);
460 if($this->debugRequests) {
461 echo "REQUEST: ".$requestBody."<br/>";
462 echo "RESPONSE: ".$responseText."<br/><br/>";
463 }
464 $responseArray = $this->json->decode($responseText);
465
466 if (!is_array($responseArray)) {
467 throw new Gpf_Exception("Response decoding failed: not array. Received text: $responseText");
468 }
469
470 if (count($responseArray) != $this->requests->getCount()) {
471 throw new Gpf_Exception("Response decoding failed: Number of responses is not same as number of requests");
472 }
473
474 $exception = false;
475 foreach ($responseArray as $index => $response) {
476 if (is_object($response) && isset($response->e)) {
477 $exception = true;
478 $this->requests->get($index)->setResponseError($response->e);
479 } else {
480 $this->requests->get($index)->setResponse($response);
481 }
482 }
483 if($exception) {
484 $messages = '';
485 foreach ($this->requests as $request) {
486 $messages .= $request->getResponseError() . "|";
487 }
488 }
489 $this->requests = new Gpf_Rpc_Array();
490 if($exception) {
491 throw new Gpf_Rpc_ExecutionException($messages);
492 }
493 }
494
495 public function setUrl($url) {
496 $this->url = $url;
497 }
498
499 public function getUrl() {
500 return $this->url;
501 }
502
503 private function getCookies() {
504 $cookiesString = '';
505 foreach ($_COOKIE as $name => $value) {
506 $cookiesString .= "$name=$value;";
507 }
508 return $cookiesString;
509 }
510 }
511
512
513} //end Gpf_Rpc_MultiRequest
514
515if (!class_exists('Gpf_Rpc_Params', false)) {
516 class Gpf_Rpc_Params extends Gpf_Object implements Gpf_Rpc_Serializable {
517 private $params;
518 const CLASS_NAME = 'C';
519 const METHOD_NAME = 'M';
520 const SESSION_ID = 'S';
521 const ACCOUNT_ID = 'aid';
522
523 function __construct($params = null) {
524 if($params === null) {
525 $this->params = new stdClass();
526 return;
527 }
528 $this->params = $params;
529 }
530
531 public static function createGetRequest($className, $methodName = 'execute', $formRequest = false, $formResponse = false) {
532 $requestData = array();
533 $requestData[self::CLASS_NAME] = $className;
534 $requestData[self::METHOD_NAME] = $methodName;
535 $requestData[Gpf_Rpc_Server::FORM_REQUEST] = $formRequest ? Gpf::YES : '';
536 $requestData[Gpf_Rpc_Server::FORM_RESPONSE] = $formResponse ? Gpf::YES : '';
537 return $requestData;
538 }
539
540 /**
541 *
542 * @param unknown_type $className
543 * @param unknown_type $methodName
544 * @param unknown_type $formRequest
545 * @param unknown_type $formResponse
546 * @return Gpf_Rpc_Params
547 */
548 public static function create($className, $methodName = 'execute', $formRequest = false, $formResponse = false) {
549 $params = new Gpf_Rpc_Params();
550 $obj = new stdClass();
551 foreach (self::createGetRequest($className, $methodName, $formRequest, $formResponse) as $name => $value) {
552 $params->add($name,$value);
553 }
554 return $params;
555 }
556
557 public function setArrayParams(array $params) {
558 foreach ($params as $name => $value) {
559 $this->add($name, $value);
560 }
561 }
562
563 public function exists($name) {
564 if(!is_object($this->params) || !property_exists($this->params, $name)) {
565 return false;
566 }
567 return true;
568 }
569
570 /**
571 *
572 * @param unknown_type $name
573 * @return mixed Return null if $name does not exist.
574 */
575 public function get($name) {
576 if(!$this->exists($name)) {
577 return null;
578 }
579 return $this->params->{$name};
580 }
581
582 public function set($name, $value) {
583 if(!$this->exists($name)) {
584 return;
585 }
586 $this->params->{$name} = $value;
587 }
588
589 public function removeParam($name) {
590 if (!$this->exists($name)) {
591 return;
592 }
593 unset($this->params->{$name});
594 }
595
596 public function add($name, $value) {
597 $this->params->{$name} = $value;
598 }
599
600 public function getClass() {
601 return $this->get(self::CLASS_NAME);
602 }
603
604 public function getMethod() {
605 return $this->get(self::METHOD_NAME);
606 }
607
608 public function getSessionId() {
609 $sessionId = $this->get(self::SESSION_ID);
610 if (is_array($sessionId) || is_object($sessionId)) {
611 $sessionId = null;
612 }
613 if ($sessionId === null || strlen(trim($sessionId)) == 0) {
614 Gpf_Session::create(new Gpf_ApiModule());
615 }
616 return $sessionId;
617 }
618
619 public function clearSessionId() {
620 $this->set(self::SESSION_ID, null);
621 }
622
623 public function getAccountId() {
624 return $this->get(self::ACCOUNT_ID);
625 }
626
627 public function toObject() {
628 return $this->params;
629 }
630
631 public function toText() {
632 throw new Gpf_Exception("Unimplemented");
633 }
634 }
635
636
637} //end Gpf_Rpc_Params
638
639if (!class_exists('Gpf_Exception', false)) {
640 class Gpf_Exception extends Exception {
641
642 private $id;
643
644 public function __construct($message,$code = null) {
645 if (defined('FULL_EXCEPTION_TRACE')) {
646 $message .= "<br>\nTRACE:<br>\n" . $this->getTraceAsString();
647 }
648 parent::__construct($message,$code);
649 }
650
651 protected function logException() {
652 Gpf_Log::error($this->getMessage());
653 }
654
655 public function setId($id) {
656 $this->id = $id;
657 }
658
659 public function getId() {
660 return $this->id;
661 }
662
663 }
664
665} //end Gpf_Exception
666
667if (!class_exists('Gpf_Data_RecordSetNoRowException', false)) {
668 class Gpf_Data_RecordSetNoRowException extends Gpf_Exception {
669 public function __construct($keyValue) {
670 parent::__construct("'Row $keyValue does not exist");
671 }
672
673 protected function logException() {
674 }
675 }
676
677} //end Gpf_Data_RecordSetNoRowException
678
679if (!class_exists('Gpf_Rpc_ExecutionException', false)) {
680 class Gpf_Rpc_ExecutionException extends Gpf_Exception {
681
682 function __construct($message) {
683 parent::__construct('RPC Execution exception: ' . $message);
684 }
685 }
686
687} //end Gpf_Rpc_ExecutionException
688
689if (!class_exists('Gpf_Rpc_Object', false)) {
690 class Gpf_Rpc_Object extends Gpf_Object implements Gpf_Rpc_Serializable {
691
692 private $object;
693
694 public function __construct($object = null) {
695 $this->object = $object;
696 }
697
698 public function toObject() {
699 if ($this->object != null) {
700 return $this->object;
701 }
702 return $this;
703 }
704
705 public function toText() {
706 return var_dump($this);
707 }
708 }
709
710
711} //end Gpf_Rpc_Object
712
713if (!class_exists('Gpf_Rpc_Request', false)) {
714 class Gpf_Rpc_Request extends Gpf_Object implements Gpf_Rpc_Serializable {
715 protected $className;
716 protected $methodName;
717 private $responseError;
718 protected $response;
719 protected $apiSessionObject = null;
720 private $useNewStyleRequestsEncoding = false;
721 private $maxTimeout = null;
722
723 /**
724 * @var Gpf_Rpc_MultiRequest
725 */
726 private $multiRequest;
727
728 /**
729 * @var Gpf_Rpc_Params
730 */
731 protected $params;
732 private $accountId = null;
733
734 public function __construct($className, $methodName, Gpf_Api_Session $apiSessionObject = null) {
735 $this->className = $className;
736 $this->methodName = $methodName;
737 $this->params = new Gpf_Rpc_Params();
738 $this->setRequiredParams($this->className, $this->methodName);
739 if($apiSessionObject != null) {
740 $this->apiSessionObject = $apiSessionObject;
741 }
742 }
743
744 public function setMaxTimeout($timeout) {
745 $this->maxTimeout = $timeout;
746 }
747
748 public function useNewStyleRequestsEncoding($useNewStyle) {
749 $this->useNewStyleRequestsEncoding = $useNewStyle;
750 }
751
752 public function setAccountId($accountId) {
753 $this->accountId = $accountId;
754 }
755
756 public function addParam($name, $value) {
757 if(is_scalar($value) || is_null($value)) {
758 $this->params->add($name, $value);
759 return;
760 }
761 if($value instanceof Gpf_Rpc_Serializable) {
762 $this->params->add($name, $value->toObject());
763 return;
764 }
765 throw new Gpf_Exception("Cannot add request param: Value ($name=$value) is not scalar or Gpf_Rpc_Serializable");
766 }
767
768 /**
769 *
770 * @return Gpf_Rpc_MultiRequest
771 */
772 public function getMultiRequest() {
773 if($this->multiRequest === null) {
774 return Gpf_Rpc_MultiRequest::getInstance();
775 }
776 return $this->multiRequest;
777 }
778
779 public function setUrl($url) {
780 $this->multiRequest = new Gpf_Rpc_MultiRequest();
781 $this->multiRequest->setUrl($url);
782 }
783
784 public function send() {
785 if($this->apiSessionObject != null) {
786 $this->multiRequest = new Gpf_Rpc_MultiRequest();
787 $this->multiRequest->setUrl($this->apiSessionObject->getUrl());
788 $this->multiRequest->useNewStyleRequestsEncoding($this->useNewStyleRequestsEncoding);
789 $this->multiRequest->setMaxTimeout($this->maxTimeout);
790 $this->multiRequest->setSessionId($this->apiSessionObject->getSessionId());
791 $this->multiRequest->setDebugRequests($this->apiSessionObject->getDebug());
792 }
793
794 $multiRequest = $this->getMultiRequest();
795 $multiRequest->add($this);
796 $multiRequest->useNewStyleRequestsEncoding($this->useNewStyleRequestsEncoding);
797 $multiRequest->setMaxTimeout($this->maxTimeout);
798 }
799
800 public function sendNow() {
801 $this->send();
802 $this->getMultiRequest()->send();
803 }
804
805 public function setResponseError($message) {
806 $this->responseError = $message;
807 }
808
809 public function getResponseError() {
810 return $this->responseError;
811 }
812
813 public function setResponse($response) {
814 $this->response = $response;
815 }
816
817 public function toObject() {
818 return $this->params->toObject();
819 }
820
821 public function toText() {
822 throw new Gpf_Exception("Unimplemented");
823 }
824
825 /**
826 *
827 * @return stdClass
828 */
829 final public function getStdResponse() {
830 if(isset($this->responseError)) {
831 throw new Gpf_Rpc_ExecutionException($this->responseError);
832 }
833 if($this->response === null) {
834 throw new Gpf_Exception("Request not executed yet.");
835 }
836 return $this->response;
837 }
838
839 final public function getResponseObject() {
840 return new Gpf_Rpc_Object($this->getStdResponse());
841 }
842
843 private function setRequiredParams($className, $methodName) {
844 $this->addParam(Gpf_Rpc_Params::CLASS_NAME, $className);
845 $this->addParam(Gpf_Rpc_Params::METHOD_NAME, $methodName);
846 }
847
848 /**
849 * @param Gpf_Rpc_Params $params
850 */
851 public function setParams(Gpf_Rpc_Params $params) {
852 $originalParams = $this->params;
853 $this->params = $params;
854 $this->setRequiredParams($originalParams->getClass(), $originalParams->getMethod());
855 }
856 }
857
858
859} //end Gpf_Rpc_Request
860
861if (!interface_exists('Gpf_HttpResponse', false)) {
862 interface Gpf_HttpResponse {
863 public function setCookieValue($name, $value = null, $expire = null, $path = null, $domain = null, $secure = null, $httpOnly = null);
864
865 public function setHeaderValue($name, $value, $replace = true, $httpResponseCode = null);
866 }
867
868} //end Gpf_HttpResponse
869
870if (!class_exists('Gpf_Http', false)) {
871 class Gpf_Http extends Gpf_Object implements Gpf_HttpResponse {
872 /**
873 *
874 * @var Gpf_HttpResponse
875 */
876 private static $instance = null;
877
878 /**
879 * @return Gpf_Http
880 */
881 private static function getInstance() {
882 if(self::$instance === null) {
883 self::$instance = new Gpf_Http();
884 }
885 return self::$instance;
886 }
887
888 public static function setInstance(Gpf_HttpResponse $instance = null) {
889 self::$instance = $instance;
890 }
891
892 public static function setCookie($name, $value = null, $expire = null, $path = null, $domain = null, $secure = null, $httpOnly = null) {
893 self::getInstance()->setCookieValue($name, $value, $expire, $path, $domain, $secure, $httpOnly);
894 }
895
896 public static function setSecuredCookie($name, $value = null, $expire = null, $path = null, $domain = null) {
897 self::getInstance()->setCookieValue($name, $value, $expire, $path, $domain, self::isSSL(), true);
898 }
899
900 public static function setHeader($name, $value, $httpResponseCode = null) {
901 self::getInstance()->setHeaderValue($name, $value, true, $httpResponseCode);
902 }
903
904 public function setHeaderValue($name, $value, $replace = true, $httpResponseCode = null) {
905 $fileName = '';
906 $line = '';
907 if(headers_sent($fileName, $line)) {
908 throw new Gpf_Exception("Headers already sent in $fileName line $line while setting header $name: $value");
909 }
910 header($name . ': ' . $value, $replace, $httpResponseCode);
911 }
912
913 public function setCookieValue($name, $value = null, $expire = null, $path = null, $domain = null, $secure = null, $httpOnly = null) {
914 $cookieExpire = '';
915 if ($expire != null) {
916 $cookieExpire = '; Expires='.gmdate('D, d M Y H:i:s', $expire) . ' GMT';
917 }
918 $cookiePath = '';
919 if ($path != null) {
920 $cookiePath = '; path='.$path;
921 }
922 $cookieDomain = '';
923 if ($domain != null) {
924 $cookieDomain = '; domain=' . $domain;
925 }
926 $cookieSecure = '';
927 if ($secure != null) {
928 $cookieSecure = '; Secure;';
929 }
930 $cookieHttpOnly = '';
931 if ($httpOnly) {
932 $cookieHttpOnly = '; HttpOnly';
933 }
934 $sameSite = '; SameSite=Lax';
935 header('Set-Cookie: ' . rawurlencode($name) . '=' . rawurlencode($value) . $cookieExpire . $cookiePath . $cookieDomain . $cookieSecure. $cookieHttpOnly . $sameSite, false);
936 }
937
938 public static function getCookie($name) {
939 if (!array_key_exists($name, $_COOKIE)) {
940 return null;
941 }
942 return $_COOKIE[$name];
943 }
944
945 public static function getUserAgent() {
946 $userAgent = self::getUserAgentPart();
947 if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
948 $userAgent .= ' - ' . $_SERVER['HTTP_ACCEPT_LANGUAGE'];
949 }
950 return $userAgent;
951 }
952
953 public static function getUserAgentPart() {
954 if (isset($_SERVER['HTTP_USER_AGENT'])) {
955 return $_SERVER['HTTP_USER_AGENT'];
956 }
957 return '';
958 }
959
960 public static function getRemoteIp($onlyRemote = false) {
961 return self::anonymizeIP(self::getRemoteIpFull($onlyRemote));
962 }
963
964 public static function getRemoteIpFull($onlyRemote = false) {
965 if (isset($GLOBALS['TRACKING_IP_ADDRESS']) && $GLOBALS['TRACKING_IP_ADDRESS'] != '') {
966 return $GLOBALS['TRACKING_IP_ADDRESS'];
967 }
968 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
969 $ip = self::parseXForwardedForIp($_SERVER['HTTP_X_FORWARDED_FOR']);
970 if ($ip != '') {
971 return $ip;
972 }
973 }
974 if (isset($_SERVER['REMOTE_ADDR'])) {
975 return $_SERVER['REMOTE_ADDR'];
976 }
977 return '';
978 }
979
980 public static function parseXForwardedForIp($ip) {
981 if (!strstr($ip, ',')) {
982 if (self::isValidIp($ip)) {
983 return $ip;
984 } else {
985 return '';
986 }
987 }
988 $ipAddresses = explode(',', $ip);
989 foreach ($ipAddresses as $ipAddress) {
990 $ipAddress = trim($ipAddress);
991 if (self::isValidIp($ipAddress)) {
992 return $ipAddress;
993 }
994 }
995 return '';
996 }
997
998
999 public static function isSSL() {
1000 if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != '' && strtolower($_SERVER['HTTPS']) != 'off') {
1001 return true;
1002 }
1003 if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') {
1004 return true;
1005 }
1006 if (isset($_SERVER['HTTP_CF_VISITOR']) && $_SERVER['HTTP_CF_VISITOR'] != '') {
1007 $cfVisitor = Gpf_Rpc_Json::decodeStatic($_SERVER['HTTP_CF_VISITOR']);
1008 if (isset($cfVisitor->scheme) && $cfVisitor->scheme == 'https') {
1009 return true;
1010 }
1011 }
1012 return false;
1013 }
1014
1015 private static function isValidIp($ip) {
1016 if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
1017 return true;
1018 }
1019 return false;
1020 }
1021
1022 public static function setStrictTransportSecurityHeader() {
1023 if (self::isSSL()) {
1024 self::setHeader('Strict-Transport-Security', 'max-age=10886400; includeSubDomains');
1025 }
1026 }
1027
1028 public static function anonymizeIP($ip) {
1029 return $ip;
1030 }
1031
1032 }
1033
1034} //end Gpf_Http
1035
1036if (!interface_exists('Gpf_Templates_HasAttributes', false)) {
1037 interface Gpf_Templates_HasAttributes {
1038 function getAttributes();
1039 }
1040
1041} //end Gpf_Templates_HasAttributes
1042
1043if (!class_exists('Gpf_Data_RecordHeader', false)) {
1044 class Gpf_Data_RecordHeader extends Gpf_Object {
1045 private $ids = array();
1046
1047 /**
1048 * Create Record header object
1049 *
1050 * @param array $headerArray
1051 */
1052 public function __construct($headerArray = null) {
1053 if($headerArray === null) {
1054 return;
1055 }
1056
1057 if (!$this->isIterable($headerArray)) {
1058 $e = new Gpf_Exception('');
1059 Gpf_Log::error('Not correct header: '.var_export($headerArray, true).' for RecordHeader, trace: '.$e->getTraceAsString());
1060
1061 return;
1062 }
1063
1064 foreach ($headerArray as $id) {
1065 $this->add($id);
1066 }
1067 }
1068
1069 public function contains($id) {
1070 return array_key_exists($id, $this->ids);
1071 }
1072
1073 public function add($id) {
1074 if (!is_numeric($id) && !is_string($id)) {
1075 throw new Gpf_Exception('Value cannot be used as key of array: '.var_export($id, true));
1076 }
1077 if ($this->contains($id)) {
1078 return;
1079 }
1080
1081 $this->ids[$id] = count($this->ids);
1082 }
1083
1084 public function getIds() {
1085 return array_keys($this->ids);
1086 }
1087
1088 public function getIndex($id) {
1089 if(!$this->contains($id)) {
1090 throw new Gpf_Exception("Unknown column '" . $id ."'");
1091 }
1092 return $this->ids[$id];
1093 }
1094
1095 public function getSize() {
1096 return count($this->ids);
1097 }
1098
1099 public function toArray() {
1100 $response = array();
1101 foreach ($this->ids as $columnId => $columnIndex) {
1102 $response[] = $columnId;
1103 }
1104 return $response;
1105 }
1106
1107 public function toObject() {
1108 $result = array();
1109 foreach ($this->ids as $columnId => $columnIndex) {
1110 $result[] = $columnId;
1111 }
1112 return $result;
1113 }
1114
1115 private function isIterable($var) {
1116 return (is_array($var) || $var instanceof Traversable || $var instanceof stdClass);
1117 }
1118 }
1119
1120
1121} //end Gpf_Data_RecordHeader
1122
1123if (!interface_exists('Gpf_Data_Row', false)) {
1124 interface Gpf_Data_Row {
1125 public function get($name);
1126
1127 public function set($name, $value);
1128 }
1129
1130} //end Gpf_Data_Row
1131
1132if (!class_exists('Gpf_Data_Record', false)) {
1133 class Gpf_Data_Record extends Gpf_Object implements Iterator, Gpf_Rpc_Serializable,
1134 Gpf_Templates_HasAttributes, Gpf_Data_Row {
1135 private $record;
1136 /**
1137 *
1138 * @var Gpf_Data_RecordHeader
1139 */
1140 private $header;
1141 private $position;
1142
1143 /**
1144 * Create record
1145 *
1146 * @param array $header
1147 * @param array $array values of record from array
1148 */
1149 public function __construct($header, $array = array()) {
1150 if (is_array($header)) {
1151 $header = new Gpf_Data_RecordHeader($header);
1152 }
1153 $this->header = $header;
1154 $this->record = array_values($array);
1155 while(count($this->record) < $this->header->getSize()) {
1156 $this->record[] = null;
1157 }
1158 }
1159
1160 function getAttributes() {
1161 $ret = array();
1162 foreach ($this as $name => $value) {
1163 $ret[$name] = $value;
1164 }
1165 return $ret;
1166 }
1167
1168 /**
1169 * @return Gpf_Data_RecordHeader
1170 */
1171 public function getHeader() {
1172 return $this->header;
1173 }
1174
1175 public function contains($id) {
1176 return $this->header->contains($id);
1177 }
1178
1179 public function get($id) {
1180 $index = $this->header->getIndex($id);
1181 return $this->record[$index];
1182 }
1183
1184 public function set($id, $value) {
1185 $index = $this->header->getIndex($id);
1186 $this->record[$index] = $value;
1187 }
1188
1189 public function add($id, $value) {
1190 $this->header->add($id);
1191 $this->set($id, $value);
1192 }
1193
1194 public function toObject() {
1195 return $this->record;
1196 }
1197
1198 public function loadFromObject(array $array) {
1199 $this->record = $array;
1200 }
1201
1202 public function toText() {
1203 return implode('-', $this->record);
1204 }
1205
1206 public function current() {
1207 if(!isset($this->record[$this->position])) {
1208 return null;
1209 }
1210 return $this->record[$this->position];
1211 }
1212
1213 public function key() {
1214 $ids = $this->header->getIds();
1215 return $ids[$this->position];
1216 }
1217
1218 public function next() {
1219 $this->position++;
1220 }
1221
1222 public function rewind() {
1223 $this->position = 0;
1224 }
1225
1226 public function valid() {
1227 return $this->position < $this->header->getSize();
1228 }
1229
1230 public function translateRowColumn($column) {
1231 $this->set($column, $this->_localizeNoReplace($this->get($column)));
1232 return;
1233 }
1234 }
1235
1236} //end Gpf_Data_Record
1237
1238if (!class_exists('Gpf_Data_Grid', false)) {
1239 class Gpf_Data_Grid extends Gpf_Object {
1240 /**
1241 * @var Gpf_Data_RecordSet
1242 */
1243 private $recordset;
1244 private $totalCount;
1245
1246 public function loadFromObject(stdClass $object) {
1247 $this->recordset = new Gpf_Data_RecordSet();
1248 $this->recordset->loadFromObject($object->rows);
1249 $this->totalCount = $object->count;
1250 }
1251
1252 /**
1253 * @return Gpf_Data_RecordSet
1254 */
1255 public function getRecordset() {
1256 return $this->recordset;
1257 }
1258
1259 public function getTotalCount() {
1260 return $this->totalCount;
1261 }
1262 }
1263
1264
1265} //end Gpf_Data_Grid
1266
1267if (!class_exists('Gpf_Data_Filter', false)) {
1268 class Gpf_Data_Filter extends Gpf_Object implements Gpf_Rpc_Serializable {
1269 const LIKE = 'L';
1270 const NOT_LIKE = 'NL';
1271 const EQUALS = 'E';
1272 const NOT_EQUALS = 'NE';
1273 const IN = 'IN';
1274 const NOT_IN = 'NOT IN';
1275
1276 const DATE_EQUALS = "D=";
1277 const DATE_GREATER = "D>";
1278 const DATE_LOWER = "D<";
1279 const DATE_EQUALS_GREATER = "D>=";
1280 const DATE_EQUALS_LOWER = "D<=";
1281 const DATERANGE_IS = "DP";
1282 const TIME_EQUALS = "T=";
1283 const TIME_GREATER = "T>";
1284 const TIME_LOWER = "T<";
1285 const TIME_EQUALS_GREATER = "T>=";
1286 const TIME_EQUALS_LOWER = "T<=";
1287
1288 const RANGE_TODAY = 'T';
1289 const RANGE_YESTERDAY = 'Y';
1290 const RANGE_LAST_7_DAYS = 'L7D';
1291 const RANGE_LAST_30_DAYS = 'L30D';
1292 const RANGE_LAST_90_DAYS = 'L90D';
1293 const RANGE_THIS_WEEK = 'TW';
1294 const RANGE_LAST_WEEK = 'LW';
1295 const RANGE_LAST_2WEEKS = 'L2W';
1296 const RANGE_LAST_WORKING_WEEK = 'LWW';
1297 const RANGE_THIS_MONTH = 'TM';
1298 const RANGE_LAST_MONTH = 'LM';
1299 const RANGE_THIS_YEAR = 'TY';
1300 const RANGE_LAST_YEAR = 'LY';
1301
1302 private $code;
1303 private $operator;
1304 private $value;
1305
1306 public function __construct($code, $operator, $value) {
1307 $this->code = $code;
1308 $this->operator = $operator;
1309 $this->value = $value;
1310 }
1311
1312 public function toObject() {
1313 return array($this->code, $this->operator, $this->value);
1314 }
1315
1316 public function toText() {
1317 throw new Gpf_Exception("Unsupported");
1318 }
1319 }
1320
1321
1322} //end Gpf_Data_Filter
1323
1324if (!class_exists('Gpf_Rpc_GridRequest', false)) {
1325 class Gpf_Rpc_GridRequest extends Gpf_Rpc_Request {
1326
1327 private $filters = array();
1328
1329 private $limit = '';
1330 private $offset = '';
1331
1332 private $sortColumn = '';
1333 private $sortAscending = false;
1334
1335 /**
1336 * @return Gpf_Data_Grid
1337 */
1338 public function getGrid() {
1339 $response = new Gpf_Data_Grid();
1340 $response->loadFromObject($this->getStdResponse());
1341 return $response;
1342 }
1343
1344 public function getFilters() {
1345 return $this->filters;
1346 }
1347
1348 /**
1349 *
1350 * @return Gpf_Rpc_Params
1351 */
1352 public function getParams() {
1353 return $this->params;
1354 }
1355
1356 /**
1357 * adds filter to grid
1358 *
1359 * @param unknown_type $code
1360 * @param unknown_type $operator
1361 * @param unknown_type $value
1362 */
1363 public function addFilter($code, $operator, $value) {
1364 $this->filters[] = new Gpf_Data_Filter($code, $operator, $value);
1365 }
1366
1367 public function setLimit($offset, $limit) {
1368 $this->offset = $offset;
1369 $this->limit = $limit;
1370 }
1371
1372 public function setSorting($sortColumn, $sortAscending = false) {
1373 $this->sortColumn = $sortColumn;
1374 $this->sortAscending = $sortAscending;
1375 }
1376
1377 public function send() {
1378 if(count($this->filters) > 0) {
1379 $this->addParam("filters", $this->getFiltersParameter());
1380 }
1381 if($this->sortColumn !== '') {
1382 $this->addParam("sort_col", $this->sortColumn);
1383 $this->addParam("sort_asc", ($this->sortAscending ? 'true' : 'false'));
1384 }
1385 if($this->offset !== '') {
1386 $this->addParam("offset", $this->offset);
1387 }
1388 if($this->limit !== '') {
1389 $this->addParam("limit", $this->limit);
1390 }
1391
1392 parent::send();
1393 }
1394
1395 protected function getFiltersParameter() {
1396 $filters = new Gpf_Rpc_Array();
1397
1398 foreach($this->filters as $filter) {
1399 $filters->add($filter);
1400 }
1401
1402 return $filters;
1403 }
1404 }
1405
1406
1407
1408} //end Gpf_Rpc_GridRequest
1409
1410if (!class_exists('Gpf_Data_RecordSet', false)) {
1411 class Gpf_Data_RecordSet extends Gpf_Object implements IteratorAggregate, Gpf_Rpc_Serializable {
1412
1413 const SORT_ASC = 'ASC';
1414 const SORT_DESC = 'DESC';
1415
1416 protected $_array;
1417 /**
1418 * @var Gpf_Data_RecordHeader
1419 */
1420 private $_header;
1421
1422 function __construct() {
1423 $this->init();
1424 }
1425
1426 public function loadFromArray($rows) {
1427 $this->setHeader($rows[0]);
1428
1429 for ($i = 1; $i < count($rows); $i++) {
1430 $this->add($rows[$i]);
1431 }
1432 }
1433
1434 public function setHeader($header) {
1435 if($header instanceof Gpf_Data_RecordHeader) {
1436 $this->_header = $header;
1437 return;
1438 }
1439 $this->_header = new Gpf_Data_RecordHeader($header);
1440 }
1441
1442 /**
1443 * @return Gpf_Data_RecordHeader
1444 */
1445 public function getHeader() {
1446 return $this->_header;
1447 }
1448
1449 public function addRecord(Gpf_Data_Record $record) {
1450 $this->_array[] = $record;
1451 }
1452
1453 public function removeRecord($i) {
1454 unset($this->_array[$i]);
1455 }
1456
1457 /**
1458 * Adds new row to RecordSet
1459 *
1460 * @param array $record array of data for all columns in record
1461 */
1462 public function add($record) {
1463 $this->addRecord($this->getRecordObject($record));
1464 }
1465
1466 /**
1467 * @return Gpf_Data_Record
1468 */
1469 public function createRecord() {
1470 return new Gpf_Data_Record($this->_header);
1471 }
1472
1473 public function toObject() {
1474 $response = array();
1475 $response[] = $this->_header->toObject();
1476 foreach ($this->_array as $record) {
1477 $response[] = $record->toObject();
1478 }
1479 return $response;
1480 }
1481
1482 public function loadFromObject($array) {
1483 if($array === null) {
1484 throw new Gpf_Exception('Array cannot be NULL');
1485 }
1486 $this->_header = new Gpf_Data_RecordHeader($array[0]);
1487 for($i = 1; $i < count($array);$i++) {
1488 $record = new Gpf_Data_Record($this->_header);
1489 $record->loadFromObject($array[$i]);
1490 $this->loadRecordFromObject($record);
1491 }
1492 }
1493
1494 public function sort($column, $sortType = 'ASC') {
1495 if (!$this->_header->contains($column)) {
1496 throw new Gpf_Exception('Undefined column');
1497 }
1498 $sorter = new Gpf_Data_RecordSet_Sorter($column, $sortType);
1499 $this->_array = $sorter->sort($this->_array);
1500 }
1501
1502 protected function loadRecordFromObject(Gpf_Data_Record $record) {
1503 $this->_array[] = $record;
1504 }
1505
1506 public function toArray() {
1507 $response = array();
1508 foreach ($this->_array as $record) {
1509 $response[] = $record->getAttributes();
1510 }
1511 return $response;
1512 }
1513
1514 public function toText() {
1515 $text = '';
1516 foreach ($this->_array as $record) {
1517 $text .= $record->toText() . "<br>\n";
1518 }
1519 return $text;
1520 }
1521
1522 /**
1523 * Return number of rows in recordset
1524 *
1525 * @return integer
1526 */
1527 public function getSize() {
1528 return count($this->_array);
1529 }
1530
1531 /**
1532 * @return Gpf_Data_Record
1533 */
1534 public function get($i) {
1535 return $this->_array[$i];
1536 }
1537
1538 /**
1539 * @param array/Gpf_Data_Record $record
1540 * @return Gpf_Data_Record
1541 */
1542 private function getRecordObject($record) {
1543 if(!($record instanceof Gpf_Data_Record)) {
1544 $record = new Gpf_Data_Record($this->_header->toArray(), $record);
1545 }
1546 return $record;
1547 }
1548
1549 private function init() {
1550 $this->_array = array();
1551 $this->_header = new Gpf_Data_RecordHeader();
1552 }
1553
1554 public function clear() {
1555 $this->init();
1556 }
1557
1558 public function load(Gpf_SqlBuilder_SelectBuilder $select) {
1559 $this->init();
1560
1561 foreach ($select->select->getColumns() as $column) {
1562 $this->_header->add($column->getAlias());
1563 }
1564 $statement = $this->createDatabase()->execute($select->toString());
1565 while($rowArray = $statement->fetchRow()) {
1566 $this->add($rowArray);
1567 }
1568 }
1569
1570 /**
1571 *
1572 * @return ArrayIterator
1573 */
1574 public function getIterator() {
1575 return new ArrayIterator($this->_array);
1576 }
1577
1578 public function getRecord($keyValue = null) {
1579 if(!array_key_exists($keyValue, $this->_array)) {
1580 return $this->createRecord();
1581 }
1582 return $this->_array[$keyValue];
1583 }
1584
1585 public function addColumn($id, $defaultValue = "") {
1586 $this->_header->add($id);
1587 foreach ($this->_array as $record) {
1588 $record->add($id, $defaultValue);
1589 }
1590 }
1591
1592 /**
1593 * @param String $headerColumn
1594 * @param String $value
1595 * @return boolean
1596 */
1597 public function existsRecordValue($headerColumn, $value) {
1598 foreach ($this->_array as $record) {
1599 if ($record->get($headerColumn) == $value) {
1600 return true;
1601 }
1602 }
1603 return false;
1604 }
1605
1606 /**
1607 * @param $headerColumn
1608 * @param $value
1609 * @return Gpf_Data_Record|null
1610 */
1611 public function getRecordByValue($headerColumn, $value) {
1612 foreach ($this->_array as $record) {
1613 if ($record->get($headerColumn) == $value) {
1614 return $record;
1615 }
1616 }
1617 return null;
1618 }
1619
1620 /**
1621 * Creates shalow copy of recordset containing only headers
1622 *
1623 * @return Gpf_Data_RecordSet
1624 */
1625 public function toShalowRecordSet() {
1626 $copy = new Gpf_Data_RecordSet();
1627 $copy->setHeader($this->_header->toArray());
1628 return $copy;
1629 }
1630 }
1631
1632 class Gpf_Data_RecordSet_Sorter {
1633
1634 private $sortColumn;
1635 private $sortType;
1636
1637 function __construct($column, $sortType) {
1638 $this->sortColumn = $column;
1639 $this->sortType = $sortType;
1640 }
1641
1642 public function sort(array $sortedArray) {
1643 usort($sortedArray, array($this, 'compareRecords'));
1644 return $sortedArray;
1645 }
1646
1647 private function compareRecords($record1, $record2) {
1648 if ($record1->get($this->sortColumn) == $record2->get($this->sortColumn)) {
1649 return 0;
1650 }
1651 return $this->compare($record1->get($this->sortColumn), $record2->get($this->sortColumn));
1652 }
1653
1654 private function compare($value1, $value2) {
1655 if ($this->sortType == Gpf_Data_RecordSet::SORT_ASC) {
1656 return (strtolower($value1) < strtolower($value2)) ? -1 : 1;
1657 }
1658 return (strtolower($value1) < strtolower($value2)) ? 1 : -1;
1659 }
1660 }
1661
1662} //end Gpf_Data_RecordSet
1663
1664if (!class_exists('Gpf_Data_IndexedRecordSet', false)) {
1665 class Gpf_Data_IndexedRecordSet extends Gpf_Data_RecordSet {
1666 private $key;
1667
1668 /**
1669 *
1670 * @param int $keyIndex specifies which column should be used as a key
1671 */
1672 function __construct($key) {
1673 parent::__construct();
1674 $this->key = $key;
1675 }
1676
1677 public function addRecord(Gpf_Data_Record $record) {
1678 $keyValue = $record->get($this->key);
1679 if (!is_numeric($keyValue) && !is_string($keyValue)) {
1680 throw new Gpf_Exception('Value cannot be used as key of array: '.var_export($keyValue, true));
1681 }
1682 $this->_array[$record->get($this->key)] = $record;
1683 }
1684
1685 /**
1686 * @param String $keyValue
1687 * @return Gpf_Data_Record
1688 */
1689 public function createRecord($keyValue = null) {
1690 if($keyValue === null) {
1691 return parent::createRecord();
1692 }
1693 if(!array_key_exists($keyValue, $this->_array)) {
1694 $record = $this->createRecord();
1695 $record->set($this->key, $keyValue);
1696 $this->addRecord($record);
1697 }
1698 return $this->_array[$keyValue];
1699 }
1700
1701 protected function loadRecordFromObject(Gpf_Data_Record $record) {
1702 $this->_array[$record->get($this->key)] = $record;
1703 }
1704
1705 /**
1706 * @param String $keyValue
1707 * @return Gpf_Data_Record
1708 */
1709 public function getRecord($keyValue = null) {
1710 if (!isset($this->_array[$keyValue])) {
1711 throw new Gpf_Data_RecordSetNoRowException($keyValue);
1712 }
1713 return $this->_array[$keyValue];
1714 }
1715
1716 /**
1717 * @param String $keyValue
1718 * @return boolean
1719 */
1720 public function existsRecord($keyValue) {
1721 return isset($this->_array[$keyValue]);
1722 }
1723
1724 /**
1725 * @param String $sortOptions (SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING)
1726 * @return boolean
1727 */
1728 public function sortByKeyValue($sortOptions) {
1729 return array_multisort($this->_array, $sortOptions);
1730 }
1731 }
1732
1733
1734} //end Gpf_Data_IndexedRecordSet
1735
1736if (!class_exists('Gpf_Net_Http_Request', false)) {
1737 class Gpf_Net_Http_Request extends Gpf_Object {
1738 const CRLF = "\r\n";
1739 const NO_SSL_VERIFYHOST = 0;
1740 const SSL_VERIFYHOST_EASY = 1;
1741 const SSL_VERIFYHOST_NORMAL = 2;
1742
1743 private $method = 'GET';
1744 private $url;
1745 private $followLocation = true;
1746
1747 //proxy server
1748 private $proxyServer = '';
1749 private $proxyPort = '';
1750 private $proxyUser = '';
1751 private $proxyPassword = '';
1752
1753 //URL components
1754 private $scheme = 'http';
1755 private $host = '';
1756 private $port = 80;
1757 private $http_user = '';
1758 private $http_password = '';
1759 private $path = '';
1760 private $query = '';
1761 private $fragment = '';
1762 private $cookies = '';
1763 private $sslVerifyHost = self::SSL_VERIFYHOST_NORMAL;
1764 private $maxTimeout = null;
1765 private $userAgent = '';
1766
1767 private $body = '';
1768 private $headers = array();
1769
1770 public function setCookies($cookies) {
1771 $this->cookies = $cookies;
1772 }
1773
1774 public function getCookies() {
1775 return $this->cookies;
1776 }
1777
1778 public function getCookiesString() {
1779 if (!is_array($this->cookies)) {
1780 return '';
1781 }
1782 return urldecode(http_build_query($this->cookies, '', ';'));
1783 }
1784
1785 public function setFollowLocation($follow) {
1786 $this->followLocation = $follow;
1787 }
1788
1789 public function getFollowLocation() {
1790 return $this->followLocation;
1791 }
1792
1793 public function getMaxTimeout() {
1794 return $this->maxTimeout;
1795 }
1796
1797 public function setMaxTimeout($timeout) {
1798 $this->maxTimeout = $timeout;
1799 }
1800
1801 public function getUserAgent() {
1802 return $this->userAgent;
1803 }
1804
1805 public function setUserAgent($userAgent) {
1806 $this->userAgent = $userAgent;
1807 }
1808
1809 public function getSslVerifyHost() {
1810 return $this->sslVerifyHost;
1811 }
1812
1813 public function setSslVerifyHost($sslVerifyHost) {
1814 $this->sslVerifyHost = $sslVerifyHost;
1815 }
1816
1817 public function getCookiesHeader() {
1818 return "Cookie: " . $this->getCookiesString();
1819 }
1820
1821 public function setUrl($url) {
1822 $this->url = $url;
1823 $this->parseUrl();
1824 }
1825
1826 public function getUrl() {
1827 return $this->url;
1828 }
1829
1830 private function parseUrl() {
1831 $components = parse_url($this->url);
1832 if (array_key_exists('scheme', $components)) {
1833 $this->scheme = $components['scheme'];
1834 }
1835 if (array_key_exists('host', $components)) {
1836 $this->host = $components['host'];
1837 }
1838 if (array_key_exists('port', $components)) {
1839 $this->port = $components['port'];
1840 }
1841 if (array_key_exists('user', $components)) {
1842 $this->http_user = $components['user'];
1843 }
1844 if (array_key_exists('pass', $components)) {
1845 $this->http_password = $components['pass'];
1846 }
1847 if (array_key_exists('path', $components)) {
1848 $this->path = $components['path'];
1849 }
1850 if (array_key_exists('query', $components)) {
1851 $this->query = $components['query'];
1852 }
1853 if (array_key_exists('fragment', $components)) {
1854 $this->fragment = $components['fragment'];
1855 }
1856 }
1857
1858 public function getScheme() {
1859 return $this->scheme;
1860 }
1861
1862 public function getHost() {
1863 if (strlen($this->proxyServer)) {
1864 return $this->proxyServer;
1865 }
1866 return $this->host;
1867 }
1868
1869 public function getPort() {
1870 if (strlen($this->proxyServer)) {
1871 return $this->proxyPort;
1872 }
1873
1874 if (strlen($this->port)) {
1875 return $this->port;
1876 }
1877 return 80;
1878 }
1879
1880 public function getHttpUser() {
1881 return $this->http_user;
1882 }
1883
1884 public function setHttpUser($user) {
1885 $this->http_user = $user;
1886 }
1887
1888 public function getHttpPassword() {
1889 return $this->http_password;
1890 }
1891
1892 public function setHttpPassword($pass) {
1893 $this->http_password = $pass;
1894 }
1895
1896 public function getPath() {
1897 return $this->path;
1898 }
1899
1900 public function getQuery() {
1901 return $this->query;
1902 }
1903
1904 public function addQueryParam($name, $value) {
1905 if (is_array($value)) {
1906 foreach($value as $key => $subValue) {
1907 $this->addQueryParam($name."[".$key."]", $subValue);
1908 }
1909 return;
1910 }
1911 $this->query .= ($this->query == '') ? '?' : '&';
1912 $this->query .= $name.'='.urlencode($value);
1913 }
1914
1915 public function getFragment() {
1916 return $this->fragment;
1917 }
1918
1919 /**
1920 * Set if request method is GET or POST
1921 *
1922 * @param string $method possible values are POST or GET
1923 */
1924 public function setMethod($method) {
1925 $method = strtoupper($method);
1926 if ($method != 'GET' && $method != 'POST' && $method != 'DELETE') {
1927 throw new Gpf_Exception('Unsupported HTTP method: ' . $method);
1928 }
1929 $this->method = $method;
1930 }
1931
1932 /**
1933 * get the request method
1934 *
1935 * @access public
1936 * @return string
1937 */
1938 public function getMethod() {
1939 return $this->method;
1940 }
1941
1942 /**
1943 * In case request should be redirected through proxy server, set proxy server settings
1944 * This function should be called after function setHost !!!
1945 *
1946 * @param string $server
1947 * @param string $port
1948 * @param string $user
1949 * @param string $password
1950 */
1951 public function setProxyServer($server, $port, $user, $password) {
1952 $this->proxyServer = $server;
1953 $this->proxyPort = $port;
1954 $this->proxyUser = $user;
1955 $this->proxyPassword = $password;
1956 }
1957
1958 public function getProxyServer() {
1959 return $this->proxyServer;
1960 }
1961
1962 public function getProxyPort() {
1963 return $this->proxyPort;
1964 }
1965
1966 public function getProxyUser() {
1967 return $this->proxyUser;
1968 }
1969
1970 public function getProxyPassword() {
1971 return $this->proxyPassword;
1972 }
1973
1974 public function setBody($body) {
1975 $this->body = $body;
1976 }
1977
1978 public function getBody() {
1979 return $this->body;
1980 }
1981
1982 /**
1983 * Set header value
1984 *
1985 * @param string $name
1986 * @param string $value
1987 */
1988 public function setHeader($name, $value) {
1989 $this->headers[$name] = $value;
1990 }
1991
1992 /**
1993 * Get header value
1994 *
1995 * @param string $name
1996 * @return string
1997 */
1998 public function getHeader($name) {
1999 if (array_key_exists($name, $this->headers)) {
2000 return $this->headers[$name];
2001 }
2002 return null;
2003 }
2004
2005 /**
2006 * Return array of headers
2007 *
2008 * @return array
2009 */
2010 public function getHeaders() {
2011 $headers = array();
2012 foreach ($this->headers as $headerName => $headerValue) {
2013 $headers[] = "$headerName: $headerValue";
2014 }
2015 return $headers;
2016 }
2017
2018 private function initHeaders() {
2019 if ($this->getPort() == '80') {
2020 $this->setHeader('Host', $this->getHost());
2021 } else {
2022 $this->setHeader('Host', $this->getHost() . ':' . $this->getPort());
2023 }
2024 if (isset($_SERVER['HTTP_USER_AGENT'])) {
2025 $this->setHeader('User-Agent', $_SERVER['HTTP_USER_AGENT']);
2026 }
2027 if (isset($_SERVER['HTTP_ACCEPT'])) {
2028 $this->setHeader('Accept', $_SERVER['HTTP_ACCEPT']);
2029 }
2030 if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) {
2031 $this->setHeader('Accept-Charset', $_SERVER['HTTP_ACCEPT_CHARSET']);
2032 }
2033 if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
2034 $this->setHeader('Accept-Language', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
2035 }
2036 if (isset($_SERVER['HTTP_REFERER'])) {
2037 $this->setHeader('Referer', $_SERVER['HTTP_REFERER']);
2038 }
2039 if ($this->getMethod() == 'POST' && !strlen($this->getHeader("Content-Type"))) {
2040 $this->setHeader("Content-Type", "application/x-www-form-urlencoded");
2041 }
2042 if ($this->getHttpPassword() != '' && $this->getHttpUser() != '') {
2043 $this->setHeader('Authorization', 'Basic ' . base64_encode($this->getHttpUser() . ':' . $this->getHttpPassword()));
2044 }
2045
2046 $this->setHeader('Content-Length', strlen($this->getBody()));
2047 $this->setHeader('Connection', 'close');
2048
2049 if (strlen($this->proxyUser)) {
2050 $this->setHeader('Proxy-Authorization',
2051 'Basic ' . base64_encode ($this->proxyUser . ':' . $this->proxyPassword));
2052 }
2053
2054 }
2055
2056 public function getUri() {
2057 $uri = $this->getPath();
2058 if (strlen($this->getQuery())) {
2059 $uri .= '?' . $this->getQuery();
2060 }
2061 return $uri;
2062 }
2063
2064 public function toString() {
2065 $this->initHeaders();
2066 $out = sprintf('%s %s HTTP/1.0' . self::CRLF, $this->getMethod(), $this->getUri());
2067 $out .= implode(self::CRLF, $this->getHeaders()) . self::CRLF . $this->getCookiesHeader() . self::CRLF;
2068 $out .= self::CRLF . $this->getBody();
2069 return $out;
2070 }
2071
2072 }
2073
2074} //end Gpf_Net_Http_Request
2075
2076if (!class_exists('Gpf_Net_Http_ClientBase', false)) {
2077 abstract class Gpf_Net_Http_ClientBase extends Gpf_Object {
2078 const CONNECTION_TIMEOUT = 20;
2079 const MAX_REDIRECTS = 5;
2080
2081 private $redirectsCount = 0;
2082
2083 /**
2084 * @param Gpf_Net_Http_Request $request
2085 * @param Gpf_Net_Http_SafeUrl_Options|null $options
2086 * @return Gpf_Net_Http_Response
2087 * @throws Gpf_Exception
2088 */
2089 public function execute(Gpf_Net_Http_Request $request, Gpf_Net_Http_SafeUrl_Options $options = null) {
2090
2091 if (!$this->isNetworkingEnabled()) {
2092 throw new Gpf_Exception($this->_('Network connections are disabled'));
2093 }
2094
2095 if (!strlen($request->getUrl())) {
2096 throw new Gpf_Exception('No URL defined.');
2097 }
2098
2099 $request->setFollowLocation(false); //security restriction (e.g. local port scanning attack)
2100 if ($options !== null) {
2101 Gpf_Net_Http_SafeUrl_Url::validateUrl($request->getUrl(), $options);
2102 }
2103
2104 $this->setProxyServer($request);
2105 if (Gpf_Php::isFunctionEnabled('curl_init') && Gpf_Php::isFunctionEnabled('curl_exec')) {
2106 $response = $this->executeWithCurl($request);
2107 } else {
2108 $response = $this->executeWithSocketOpen($request);
2109 }
2110
2111 if ($options != null && $options->getFollowLocation() && $options->getFollowLocationLimit() > $this->redirectsCount && ($response->getResponseCode() == 301 || $response->getResponseCode() == 302)) {
2112 //follow location
2113 $this->redirectsCount ++;
2114 $location = empty($response->getHeaders()['Location']) ? $response->getHeaders()['location'] : $response->getHeaders()['Location'];
2115 $request->setUrl($location);
2116 return $this->execute($request, $options);
2117 }
2118
2119 return $response;
2120 }
2121
2122 protected abstract function isNetworkingEnabled();
2123
2124 /**
2125 * @param Gpf_Net_Http_Request $request
2126 * @return Gpf_Net_Http_Response
2127 */
2128 private function executeWithSocketOpen(Gpf_Net_Http_Request $request) {
2129 $timeout = self::CONNECTION_TIMEOUT;
2130 if ($request->getMaxTimeout() != '') {
2131 $timeout = $request->getMaxTimeout();
2132 }
2133
2134 $scheme = ($request->getScheme() == 'ssl' || $request->getScheme() == 'https') ? 'ssl://' : '';
2135 $port = ($scheme == 'ssl://' && $request->getPort() == 80 ? '443' : $request->getPort());
2136 $proxySocket = @fsockopen($scheme . $request->getHost(), $port, $errorNr,
2137 $errorMessage, $timeout);
2138
2139 if($proxySocket === false) {
2140 $gpfErrorMessage = $this->_sys('Could not connect to server: %s:%s, Failed with error: %s', $request->getHost(), $request->getPort(), $errorMessage);
2141 Gpf_Log::error($gpfErrorMessage);
2142 throw new Gpf_Exception($gpfErrorMessage);
2143 }
2144
2145 $requestText = $request->toString();
2146
2147 $result = @fwrite($proxySocket, $requestText);
2148 if($result === false || $result != strlen($requestText)) {
2149 @fclose($proxySocket);
2150 $gpfErrorMessage = $this->_sys('Could not send request to server %s:%s', $request->getHost(), $request->getPort());
2151 Gpf_Log::error($gpfErrorMessage);
2152 throw new Gpf_Exception($gpfErrorMessage);
2153 }
2154
2155 $result = '';
2156 while (false === @feof($proxySocket)) {
2157 try {
2158 if(false === ($data = @fread($proxySocket, 8192))) {
2159 Gpf_Log::error($this->_sys('Could not read from proxy socket'));
2160 throw new Gpf_Exception("could not read from proxy socket");
2161 }
2162 $result .= $data;
2163 } catch (Exception $e) {
2164 Gpf_Log::error($this->_sys('Proxy failed: %s', $e->getMessage()));
2165 @fclose($proxySocket);
2166 throw new Gpf_Exception($this->_('Proxy failed: %s', $e->getMessage()));
2167 }
2168 }
2169 @fclose($proxySocket);
2170
2171 $response = new Gpf_Net_Http_Response();
2172 $response->setResponseText($result);
2173
2174 return $response;
2175 }
2176
2177
2178 /**
2179 * @param Gpf_Net_Http_Request $request
2180 * @return Gpf_Net_Http_Response
2181 * */
2182 private function executeWithCurl(Gpf_Net_Http_Request $request) {
2183 $session = curl_init($request->getUrl());
2184
2185 if ($request->getMethod() == 'POST') {
2186 @curl_setopt ($session, CURLOPT_POST, true);
2187 @curl_setopt ($session, CURLOPT_POSTFIELDS, $request->getBody());
2188 } elseif ($request->getMethod() == 'DELETE') {
2189 curl_setopt($session, CURLOPT_CUSTOMREQUEST, 'DELETE');
2190 curl_setopt($session, CURLOPT_POSTFIELDS, $request->getBody());
2191 }
2192
2193 $cookies = $request->getCookiesString();
2194 if($cookies) {
2195 @curl_setopt($session, CURLOPT_COOKIE, $cookies);
2196 }
2197
2198 @curl_setopt($session, CURLOPT_HEADER, true);
2199 @curl_setopt($session, CURLOPT_CONNECTTIMEOUT, self::CONNECTION_TIMEOUT);
2200 @curl_setopt($session, CURLOPT_HTTPHEADER, $request->getHeaders());
2201 if ($request->getFollowLocation()) {
2202 @curl_setopt($session, CURLOPT_FOLLOWLOCATION, true);
2203 }
2204 @curl_setopt($session, CURLOPT_MAXREDIRS, self::MAX_REDIRECTS);
2205 @curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
2206 @curl_setopt($session, CURLOPT_FAILONERROR, true);
2207 if ($request->getHttpPassword() != '' && $request->getHttpUser() != '') {
2208 @curl_setopt($session, CURLOPT_USERPWD, $request->getHttpUser() . ":" . $request->getHttpPassword());
2209 @curl_setopt($session, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
2210 }
2211 @curl_setopt($session, CURLOPT_SSL_VERIFYHOST, $request->getSslVerifyHost());
2212 if ($request->getSslVerifyHost() == Gpf_Net_Http_Request::NO_SSL_VERIFYHOST) {
2213 @curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false);
2214 } else {
2215 @curl_setopt($session, CURLOPT_SSL_VERIFYPEER, true);
2216 }
2217 @curl_setopt($session, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
2218 if ($request->getMaxTimeout() != '') {
2219 @curl_setopt($session, CURLOPT_TIMEOUT, $request->getMaxTimeout());
2220 }
2221 if ($request->getUserAgent() != '') {
2222 @curl_setopt($session, CURLOPT_USERAGENT, $request->getUserAgent());
2223 }
2224
2225 $this->setupCurlProxyServer($session, $request);
2226
2227 // Make the call
2228 $result = curl_exec($session);
2229 $error = curl_error($session);
2230 $contentType = curl_getinfo($session, CURLINFO_CONTENT_TYPE);
2231 curl_close($session);
2232
2233 if (strlen($error)) {
2234 throw new Gpf_Exception('Curl error: ' . $error . '; ' . $request->getUrl());
2235 }
2236
2237 $response = new Gpf_Net_Http_Response();
2238 $response->setResponseText($result);
2239 $response->setContentType($contentType);
2240
2241 return $response;
2242 }
2243
2244 protected function setProxyServer(Gpf_Net_Http_Request $request) {
2245 try {
2246 $proxyServer = Gpf_Settings::get(Gpf_Settings_Gpf::PROXY_SERVER_SETTING_NAME);
2247 $proxyPort = Gpf_Settings::get(Gpf_Settings_Gpf::PROXY_PORT_SETTING_NAME);
2248 $proxyUser = Gpf_Settings::get(Gpf_Settings_Gpf::PROXY_USER_SETTING_NAME);
2249 $proxyPassword = Gpf_Settings::get(Gpf_Settings_Gpf::PROXY_PASSWORD_SETTING_NAME);
2250 $request->setProxyServer($proxyServer, $proxyPort, $proxyUser, $proxyPassword);
2251 } catch (Gpf_Exception $e) {
2252 $request->setProxyServer('', '', '', '');
2253 }
2254 }
2255
2256 private function setupCurlProxyServer($curlSession, Gpf_Net_Http_Request $request) {
2257 if (strlen($request->getProxyServer()) && strlen($request->getProxyPort())) {
2258 @curl_setopt($curlSession, CURLOPT_PROXY, $request->getProxyServer() . ':' . $request->getProxyPort());
2259 if (strlen($request->getProxyUser())) {
2260 @curl_setopt($curlSession, CURLOPT_PROXYUSERPWD, $request->getProxyUser() . ':' . $request->getProxyPassword());
2261 }
2262 }
2263 }
2264 }
2265
2266} //end Gpf_Net_Http_ClientBase
2267
2268if (!class_exists('Gpf_Net_Http_Response', false)) {
2269 class Gpf_Net_Http_Response extends Gpf_Object {
2270
2271 private $responseText = '';
2272 private $header = '';
2273 private $body = '';
2274 private $contentType = '';
2275
2276 public function setResponseText($responseText) {
2277 $this->responseText = $responseText;
2278 $this->parse();
2279 }
2280
2281 public function setContentType($contentType) {
2282 $this->contentType = $contentType;
2283 }
2284
2285 /**
2286 * @return string
2287 */
2288 public function getContentType() {
2289 return $this->contentType;
2290 }
2291
2292 public function getHeadersText() {
2293 return $this->header;
2294 }
2295
2296 private function getHeaderPosition($pos) {
2297 return strpos($this->responseText, "\r\n\r\nHTTP", $pos);
2298 }
2299
2300 public function getBody() {
2301 return $this->body;
2302 }
2303
2304 private function parse() {
2305 $offset = 0;
2306 while ($this->getHeaderPosition($offset)) {
2307 $offset = $this->getHeaderPosition($offset) + 4;
2308 }
2309 if (($pos = strpos($this->responseText, "\r\n\r\n", $offset)) > 0) {
2310 $this->body = substr($this->responseText, $pos + 4);
2311 $this->header = substr($this->responseText, $offset, $pos - $offset);
2312 return;
2313 }
2314 $this->body = '';
2315 $this->header = '';
2316 }
2317
2318
2319
2320 public function getResponseCode() {
2321 $headers = $this->getHeaders();
2322 if ($headers == false || !isset($headers['status'])) {
2323 return false;
2324 }
2325 preg_match('/.*?\s([0-9]*?)\s.*/', $headers['status'], $match);
2326 if (!isset($match[1])) {
2327 return false;
2328 }
2329 return $match[1];
2330 }
2331
2332 public function getHeaders() {
2333 return $this->httpParseHeaders($this->header);
2334 }
2335
2336 private function httpParseHeaders($headers = false){
2337 if($headers == false){
2338 return false;
2339 }
2340 $headerdata = false;
2341 $headers = str_replace("\r","",$headers);
2342 $headers = explode("\n",$headers);
2343 foreach($headers as $value){
2344 $header = explode(": ",$value);
2345 if($header[0] && !isset($header[1])){
2346 $headerdata['status'] = $header[0];
2347 } elseif($header[0] && isset($header[1])){
2348 $headerdata[$header[0]] = $header[1];
2349 }
2350 }
2351 return $headerdata;
2352 }
2353 }
2354
2355} //end Gpf_Net_Http_Response
2356
2357if (!class_exists('Gpf_Rpc_Form', false)) {
2358 class Gpf_Rpc_Form extends Gpf_Object implements Gpf_Rpc_Serializable, IteratorAggregate {
2359 const FIELD_NAME = "name";
2360 const FIELD_VALUE = "value";
2361 const FIELD_ERROR = "error";
2362 const FIELD_VALUES = "values";
2363
2364 private $isError = false;
2365 private $errorMessage = "";
2366 private $infoMessage = "";
2367 private $status;
2368 /**
2369 * @var Gpf_Data_IndexedRecordSet
2370 */
2371 private $fields;
2372 /**
2373 * @var Gpf_Rpc_Form_Validator_FormValidatorCollection
2374 */
2375 private $validators;
2376
2377 public function __construct(Gpf_Rpc_Params $params = null) {
2378 $this->fields = new Gpf_Data_IndexedRecordSet(self::FIELD_NAME);
2379
2380 $header = new Gpf_Data_RecordHeader();
2381 $header->add(self::FIELD_NAME);
2382 $header->add(self::FIELD_VALUE);
2383 $header->add(self::FIELD_VALUES);
2384 $header->add(self::FIELD_ERROR);
2385 $this->fields->setHeader($header);
2386
2387 $this->validator = new Gpf_Rpc_Form_Validator_FormValidatorCollection($this);
2388
2389 if($params) {
2390 $this->loadFieldsFromArray($params->get("fields"));
2391 }
2392 }
2393
2394 /**
2395 * @param $validator
2396 * @param $fieldName
2397 * @param $fieldLabel
2398 */
2399 public function addValidator(Gpf_Rpc_Form_Validator_Validator $validator, $fieldName, $fieldLabel = null) {
2400 $this->validator->addValidator($validator, $fieldName, $fieldLabel);
2401 }
2402
2403 /**
2404 * @return boolean
2405 */
2406 public function validate() {
2407 return $this->validator->validate();
2408 }
2409
2410 public function loadFieldsFromArray($fields) {
2411 if (is_array($fields)) {
2412 for ($i = 1; $i < count($fields); $i++) {
2413 $field = $fields[$i];
2414 $this->fields->add($field);
2415 }
2416 }
2417 }
2418
2419 /**
2420 *
2421 * @return ArrayIterator
2422 */
2423 public function getIterator() {
2424 return $this->fields->getIterator();
2425 }
2426
2427 public function addField($name, $value) {
2428 $record = $this->fields->createRecord($name);
2429 $record->set(self::FIELD_VALUE, $value);
2430 }
2431
2432 public function removeField($name) {
2433 if ($this->existsField($name)) {
2434 $this->fields->removeRecord($name);
2435 }
2436 }
2437
2438 public function setField($name, $value, $values = null, $error = "") {
2439 $record = $this->fields->createRecord($name);
2440 $record->set(self::FIELD_VALUE, $value);
2441 $record->set(self::FIELD_VALUES, $values);
2442 $record->set(self::FIELD_ERROR, $error);
2443 }
2444
2445 public function setFieldError($name, $error) {
2446 $this->isError = true;
2447 $record = $this->fields->getRecord($name);
2448 $record->set(self::FIELD_ERROR, $error);
2449 }
2450
2451 public function getFieldValue($name) {
2452 $record = $this->fields->getRecord($name);
2453 return $record->get(self::FIELD_VALUE);
2454 }
2455
2456 public function getFieldValues($name) {
2457 $record = $this->fields->getRecord($name);
2458 return $record->get(self::FIELD_VALUES);
2459 }
2460
2461 public function getFieldError($name) {
2462 $record = $this->fields->getRecord($name);
2463 return $record->get(self::FIELD_ERROR);
2464 }
2465
2466 public function existsField($name) {
2467 return $this->fields->existsRecord($name);
2468 }
2469
2470 public function load(Gpf_Data_Row $row) {
2471 foreach($row as $columnName => $columnValue) {
2472 $this->setField($columnName, $row->get($columnName));
2473 }
2474 }
2475
2476 /**
2477 * @return Gpf_Data_IndexedRecordSet
2478 */
2479 public function getFields() {
2480 return $this->fields;
2481 }
2482
2483 public function fill(Gpf_Data_Row $row, array $writableFields = array()) {
2484 foreach ($this->fields as $field) {
2485 if (count($writableFields) > 0 && !in_array($field->get(self::FIELD_NAME), $writableFields)) {
2486 continue;
2487 }
2488 try {
2489 $row->set($field->get(self::FIELD_NAME), $field->get(self::FIELD_VALUE));
2490 } catch (Exception $e) {
2491 }
2492 }
2493 }
2494
2495 public function toObject() {
2496 $response = new stdClass();
2497 $response->fields = $this->fields->toObject();
2498 if ($this->isSuccessful()) {
2499 $response->success = Gpf::YES;
2500 $response->message = $this->infoMessage;
2501 } else {
2502 $response->success = "N";
2503 $response->message = $this->getErrorMessage();
2504 }
2505 return $response;
2506 }
2507
2508 public function loadFromObject(stdClass $object) {
2509 if ($object->success == Gpf::YES) {
2510 $this->setInfoMessage($object->message);
2511 } else {
2512 $this->setErrorMessage($object->message);
2513 }
2514
2515 $this->fields = new Gpf_Data_IndexedRecordSet(self::FIELD_NAME);
2516 $this->fields->loadFromObject($object->fields);
2517 }
2518
2519 public function toText() {
2520 ob_start();
2521 var_dump($this->toObject());
2522 return ob_get_clean();
2523 }
2524
2525 public function setErrorMessage($message) {
2526 $this->isError = true;
2527 $this->errorMessage = $message;
2528 }
2529
2530 public function getErrorMessage() {
2531 if ($this->isError) {
2532 if ($this->errorMessage != '') {
2533 return $this->errorMessage;
2534 }
2535 return $this->getFieldErrorMessage();
2536 }
2537 return '';
2538 }
2539
2540 public function getFieldErrorMessage() {
2541 foreach ($this->getIterator() as $field) {
2542 if ($field->get(self::FIELD_ERROR) != '') {
2543 return $field->get(self::FIELD_ERROR);
2544 }
2545 }
2546 return '';
2547 }
2548
2549 public function setInfoMessage($message) {
2550 $this->infoMessage = $message;
2551 }
2552
2553 public function setSuccessful() {
2554 $this->isError = false;
2555 }
2556
2557 public function getInfoMessage() {
2558 if ($this->isError) {
2559 return "";
2560 }
2561 return $this->infoMessage;
2562 }
2563
2564
2565 /**
2566 * @return boolean
2567 */
2568 public function isSuccessful() {
2569 return !$this->isError;
2570 }
2571
2572 /**
2573 * @return boolean
2574 */
2575 public function isError() {
2576 return $this->isError;
2577 }
2578 }
2579
2580
2581} //end Gpf_Rpc_Form
2582
2583if (!class_exists('Gpf_Rpc_Form_Validator_FormValidatorCollection', false)) {
2584 class Gpf_Rpc_Form_Validator_FormValidatorCollection extends Gpf_Object {
2585
2586 /**
2587 * @var array<Gpf_Rpc_Form_Validator_FieldValidator>
2588 */
2589 private $validators;
2590 /**
2591 * @var Gpf_Rpc_Form
2592 */
2593 private $form;
2594
2595 public function __construct(Gpf_Rpc_Form $form) {
2596 $this->form = $form;
2597 $this->validators = array();
2598 }
2599
2600 /**
2601 * @param $fieldName
2602 * @param $validator
2603 */
2604 public function addValidator(Gpf_Rpc_Form_Validator_Validator $validator, $fieldName, $fieldLabel = null) {
2605 if (!array_key_exists($fieldName, $this->validators)) {
2606 $this->validators[$fieldName] = new Gpf_Rpc_Form_Validator_FieldValidator(($fieldLabel === null ? $fieldName : $fieldLabel));
2607 }
2608 $this->validators[$fieldName]->addValidator($validator);
2609 }
2610
2611 /**
2612 * @return boolean
2613 */
2614 public function validate() {
2615 $errorMsg = false;
2616 foreach ($this->validators as $fieldName => $fieldValidator) {
2617 try {
2618 $value = $this->form->getFieldValue($fieldName);
2619 } catch (Gpf_Data_RecordSetNoRowException $e) {
2620 $value = '';
2621 }
2622 if (!$fieldValidator->validate($value)) {
2623 $errorMsg = true;
2624 $this->form->setFieldError($fieldName, $fieldValidator->getMessage());
2625 }
2626 }
2627 if ($errorMsg) {
2628 $this->form->setErrorMessage($this->_('There were errors, please check the highlighted fields'));
2629 }
2630 return !$errorMsg;
2631 }
2632 }
2633
2634} //end Gpf_Rpc_Form_Validator_FormValidatorCollection
2635
2636if (!class_exists('Gpf_Rpc_FormRequest', false)) {
2637 class Gpf_Rpc_FormRequest extends Gpf_Rpc_Request {
2638 /**
2639 * @var Gpf_Rpc_Form
2640 */
2641 private $fields;
2642
2643 public function __construct($className, $methodName, Gpf_Api_Session $apiSessionObject = null) {
2644 parent::__construct($className, $methodName, $apiSessionObject);
2645 $this->fields = new Gpf_Rpc_Form();
2646 }
2647
2648 public function send() {
2649 $this->addParam('fields', $this->fields->getFields());
2650 parent::send();
2651 }
2652
2653 /**
2654 * @return Gpf_Rpc_Form
2655 */
2656 public function getForm() {
2657 $response = new Gpf_Rpc_Form();
2658 $response->loadFromObject($this->getStdResponse());
2659 return $response;
2660 }
2661
2662 public function setField($name, $value) {
2663 if (is_scalar($value) || $value instanceof Gpf_Rpc_Serializable) {
2664 $this->fields->setField($name, $value);
2665 } else {
2666 throw new Gpf_Exception("Not supported value");
2667 }
2668 }
2669
2670 public function setFields(Gpf_Data_IndexedRecordSet $fields) {
2671 $this->fields->loadFieldsFromArray($fields->toArray());
2672 }
2673 }
2674
2675} //end Gpf_Rpc_FormRequest
2676
2677if (!class_exists('Gpf_Rpc_RecordSetRequest', false)) {
2678 class Gpf_Rpc_RecordSetRequest extends Gpf_Rpc_Request {
2679
2680 /**
2681 * @return Gpf_Data_IndexedRecordSet
2682 */
2683 public function getIndexedRecordSet($key) {
2684 $response = new Gpf_Data_IndexedRecordSet($key);
2685 $response->loadFromObject($this->getStdResponse());
2686 return $response;
2687 }
2688
2689
2690 /**
2691 * @return Gpf_Data_RecordSet
2692 */
2693 public function getRecordSet() {
2694 $response = new Gpf_Data_RecordSet();
2695 $response->loadFromObject($this->getStdResponse());
2696 return $response;
2697 }
2698 }
2699
2700
2701} //end Gpf_Rpc_RecordSetRequest
2702
2703if (!class_exists('Gpf_Rpc_DataRequest', false)) {
2704 class Gpf_Rpc_DataRequest extends Gpf_Rpc_Request {
2705 /**
2706 * @var Gpf_Rpc_Data
2707 */
2708 private $data;
2709
2710 private $filters = array();
2711
2712 public function __construct($className, $methodName, Gpf_Api_Session $apiSessionObject = null) {
2713 parent::__construct($className, $methodName, $apiSessionObject);
2714 $this->data = new Gpf_Rpc_Data();
2715 }
2716
2717 /**
2718 * @return Gpf_Rpc_Data
2719 */
2720 public function getData() {
2721 $response = new Gpf_Rpc_Data();
2722 $response->loadFromObject($this->getStdResponse());
2723 return $response;
2724 }
2725
2726 public function setField($name, $value) {
2727 if (is_scalar($value) || $value instanceof Gpf_Rpc_Serializable) {
2728 $this->data->setParam($name, $value);
2729 } else {
2730 throw new Gpf_Exception("Not supported value");
2731 }
2732 }
2733
2734 /**
2735 * adds filter to grid
2736 *
2737 * @param unknown_type $code
2738 * @param unknown_type $operator
2739 * @param unknown_type $value
2740 */
2741 public function addFilter($code, $operator, $value) {
2742 $this->filters[] = new Gpf_Data_Filter($code, $operator, $value);
2743 }
2744
2745 public function send() {
2746 $this->addParam('data', $this->data->getParams());
2747
2748 if(count($this->filters) > 0) {
2749 $this->addParam("filters", $this->addFiltersParameter());
2750 }
2751 parent::send();
2752 }
2753
2754 private function addFiltersParameter() {
2755 $filters = new Gpf_Rpc_Array();
2756
2757 foreach($this->filters as $filter) {
2758 $filters->add($filter);
2759 }
2760
2761 return $filters;
2762 }
2763 }
2764
2765} //end Gpf_Rpc_DataRequest
2766
2767if (!class_exists('Gpf_Rpc_Data', false)) {
2768 class Gpf_Rpc_Data extends Gpf_Object implements Gpf_Rpc_Serializable {
2769 const NAME = "name";
2770 const VALUE = "value";
2771 const DATA = "data";
2772 const ID = "id";
2773
2774 /**
2775 * @var Gpf_Data_IndexedRecordSet
2776 */
2777 private $params;
2778
2779 /**
2780 * @var string
2781 */
2782 private $id;
2783
2784
2785 /**
2786 * @var Gpf_Rpc_FilterCollection
2787 */
2788 private $filters;
2789
2790 /**
2791 * @var Gpf_Data_IndexedRecordSet
2792 */
2793 private $response;
2794
2795 /**
2796 *
2797 * @return Gpf_Data_IndexedRecordSet
2798 */
2799 public function getParams() {
2800 return $this->params;
2801 }
2802
2803 /**
2804 * Create instance to handle DataRequest
2805 *
2806 * @param Gpf_Rpc_Params $params
2807 */
2808 public function __construct(Gpf_Rpc_Params $params = null) {
2809 if($params === null) {
2810 $params = new Gpf_Rpc_Params();
2811 }
2812
2813 $this->filters = new Gpf_Rpc_FilterCollection($params);
2814
2815 $this->params = new Gpf_Data_IndexedRecordSet(self::NAME);
2816 $this->params->setHeader(array(self::NAME, self::VALUE));
2817
2818 if ($params->exists(self::DATA)) {
2819 $this->loadParamsFromArray($params->get(self::DATA));
2820 }
2821
2822 $this->id = $params->get(self::ID);
2823
2824 $this->response = new Gpf_Data_IndexedRecordSet(self::NAME);
2825 $this->response->setHeader(array(self::NAME, self::VALUE));
2826 }
2827
2828 /**
2829 * Return id
2830 *
2831 * @return string
2832 */
2833 public function getId() {
2834 return $this->id;
2835 }
2836
2837 /**
2838 * Return parameter value
2839 *
2840 * @param String $name
2841 * @return unknown
2842 */
2843 public function getParam($name) {
2844 try {
2845 return $this->params->getRecord($name)->get(self::VALUE);
2846 } catch (Gpf_Data_RecordSetNoRowException $e) {
2847 return null;
2848 }
2849 }
2850
2851 public function setParam($name, $value) {
2852 self::setValueToRecordset($this->params, $name, $value);
2853 }
2854
2855 public function loadFromObject(array $object) {
2856 $this->response->loadFromObject($object);
2857 $this->params->loadFromObject($object);
2858 }
2859
2860 /**
2861 * @return Gpf_Rpc_FilterCollection
2862 */
2863 public function getFilters() {
2864 return $this->filters;
2865 }
2866
2867 private static function setValueToRecordset(Gpf_Data_IndexedRecordSet $recordset, $name, $value) {
2868 try {
2869 $record = $recordset->getRecord($name);
2870 } catch (Gpf_Data_RecordSetNoRowException $e) {
2871 $record = $recordset->createRecord();
2872 $record->set(self::NAME, $name . '');
2873 $recordset->addRecord($record);
2874 }
2875 $record->set(self::VALUE, $value);
2876 }
2877
2878 public function setValue($name, $value) {
2879 self::setValueToRecordset($this->response, $name, $value);
2880 }
2881
2882 public function getSize() {
2883 return $this->response->getSize();
2884 }
2885
2886 public function getValue($name) {
2887 try {
2888 return $this->response->getRecord($name)->get(self::VALUE);
2889 } catch (Gpf_Data_RecordSetNoRowException $e) {
2890 }
2891 return null;
2892 }
2893
2894 public function toObject() {
2895 return $this->response->toObject();
2896 }
2897
2898 public function toText() {
2899 return $this->response->toText();
2900 }
2901
2902 private function loadParamsFromArray($data) {
2903 for ($i = 1; $i < count($data); $i++) {
2904 $this->params->add($data[$i]);
2905 }
2906 }
2907 }
2908
2909} //end Gpf_Rpc_Data
2910
2911if (!class_exists('Gpf_Rpc_FilterCollection', false)) {
2912 class Gpf_Rpc_FilterCollection extends Gpf_Object implements IteratorAggregate {
2913
2914 /**
2915 * @var Gpf_SqlBuilder_Filter[]
2916 */
2917 private $filters;
2918
2919 public function __construct(Gpf_Rpc_Params $params = null) {
2920 $this->filters = array();
2921 if ($params != null) {
2922 $this->init($params);
2923 }
2924 }
2925
2926 public function add(array $filterArray) {
2927 $this->filters[] = new Gpf_SqlBuilder_Filter($filterArray);
2928 }
2929
2930 public function addFilter(Gpf_SqlBuilder_Filter $filter) {
2931 $this->filters[] = $filter;
2932 }
2933
2934 public function loadDefaultFilterCollection($filterType) {
2935 if ($filterType == '') {
2936 return;
2937 }
2938
2939 $filterId = Gpf_Db_Table_Filters::getInstance()->getDefaultFilterId($filterType);
2940 if ($filterId == '') {
2941 return;
2942 }
2943 $this->loadFilterById($filterId);
2944 }
2945
2946 public function loadFilterById($filterId) {
2947 $filters = new Gpf_Db_FilterCondition();
2948 $filters->setFilterId($filterId);
2949 $collection = $filters->loadCollection();
2950
2951 foreach ($collection as $filterCondition) {
2952 if ($filterCondition->get(Gpf_Db_Table_FilterConditions::VALUE) != '') {
2953 $this->add(array(
2954 Gpf_SqlBuilder_Filter::FILTER_CODE => $filterCondition->get(Gpf_Db_Table_FilterConditions::CODE),
2955 Gpf_SqlBuilder_Filter::FILTER_OPERATOR => $filterCondition->get(Gpf_Db_Table_FilterConditions::OPERATOR),
2956 Gpf_SqlBuilder_Filter::FILTER_VALUE => $filterCondition->get(Gpf_Db_Table_FilterConditions::VALUE)
2957 ));
2958 }
2959 }
2960 }
2961
2962 private function init(Gpf_Rpc_Params $params) {
2963 $filtersArray = $params->get("filters");
2964 if (!is_array($filtersArray)) {
2965 return;
2966 }
2967 foreach ($filtersArray as $filterArray) {
2968 $this->add($filterArray);
2969 }
2970 }
2971
2972 /**
2973 *
2974 * @return ArrayIterator
2975 */
2976 public function getIterator() {
2977 return new ArrayIterator($this->filters);
2978 }
2979
2980 public function addTo(Gpf_SqlBuilder_WhereClause $whereClause) {
2981 foreach ($this->filters as $filter) {
2982 $filter->addTo($whereClause);
2983 }
2984 }
2985
2986 /**
2987 * Returns first filter with specified code.
2988 * If filter with specified code does not exists null is returned.
2989 *
2990 * @param string $code
2991 * @return Gpf_SqlBuilder_Filter[]
2992 */
2993 public function getFilter($code) {
2994 $filters = array();
2995 foreach ($this->filters as $filter) {
2996 if ($filter->getCode() == $code) {
2997 $filters[] = $filter;
2998 }
2999 }
3000 return $filters;
3001 }
3002
3003 public function isFilter($code) {
3004 foreach ($this->filters as $filter) {
3005 if ($filter->getCode() == $code) {
3006 return true;
3007 }
3008 }
3009 return false;
3010 }
3011
3012 public function getFilterValue($code) {
3013 $filters = $this->getFilter($code);
3014 if (count($filters) == 1) {
3015 return $filters[0]->getValue();
3016 }
3017 return "";
3018 }
3019
3020 public function matches(Gpf_Data_Record $row) {
3021 foreach ($this->filters as $filter) {
3022 if (!$filter->matches($row)) {
3023 return false;
3024 }
3025 }
3026 return true;
3027 }
3028
3029 public function getSize() {
3030 return count($this->filters);
3031 }
3032 }
3033
3034} //end Gpf_Rpc_FilterCollection
3035
3036if (!class_exists('Gpf_Rpc_PhpErrorHandler', false)) {
3037 class Gpf_Rpc_PhpErrorHandler {
3038
3039 private $errorTypes;
3040 private $callback;
3041 private $params;
3042
3043 public function handleError($severity, $message, $filename, $lineno) {
3044 if (error_reporting() == 0) {
3045 return;
3046 }
3047 if (error_reporting() & $severity) {
3048 $exception = new ErrorException($message, 0, $severity, $filename, $lineno);
3049 Gpf_Log::warning('Error calling function: ' . $this->getFunctionName($this->callback) . ', with parameters: ' . var_export($this->params, true) . '. Error trace: ' . $exception->getTraceAsString());
3050 if ($severity != E_WARNING && $severity != E_NOTICE) {
3051 throw $exception;
3052 }
3053 }
3054 }
3055
3056 public function callMethod($callback, $params = null, $errorTypes = E_ALL) {
3057 $this->callback = $callback;
3058 $this->errorTypes = $errorTypes;
3059 $this->params = $params;
3060 set_error_handler(array(&$this, 'handleError'), $errorTypes);
3061 try {
3062 $result = call_user_func_array($callback, $params);
3063 } catch (ErrorException $e) {
3064 $result = null;
3065 }
3066 restore_error_handler();
3067 return $result;
3068 }
3069
3070 private function getFunctionName($callback) {
3071 if (is_array($callback)) {
3072 return get_class($callback[0]).'->'.$callback[1];
3073 }
3074 return $callback;
3075 }
3076 }
3077
3078
3079} //end Gpf_Rpc_PhpErrorHandler
3080
3081if (!class_exists('Gpf_Php', false)) {
3082 class Gpf_Php {
3083
3084 /**
3085 * Check if function is enabled and exists in php
3086 *
3087 * @param $functionName
3088 * @return boolean Returns true if function exists and is enabled
3089 */
3090 public static function isFunctionEnabled($functionName) {
3091 if (function_exists($functionName) && strstr(ini_get("disable_functions"), $functionName) === false) {
3092 return true;
3093 }
3094 return false;
3095 }
3096
3097 /**
3098 * Check if extension is loaded
3099 *
3100 * @param $extensionName
3101 * @return boolean Returns true if extension is loaded
3102 */
3103 public static function isExtensionLoaded($extensionName) {
3104 return extension_loaded($extensionName);
3105 }
3106
3107 }
3108
3109} //end Gpf_Php
3110
3111if (!class_exists('Gpf_Rpc_ActionRequest', false)) {
3112 class Gpf_Rpc_ActionRequest extends Gpf_Rpc_Request {
3113
3114 /**
3115 * @return Gpf_Rpc_Action
3116 */
3117 public function getAction() {
3118 $action = new Gpf_Rpc_Action(new Gpf_Rpc_Params());
3119 $action->loadFromObject($this->getStdResponse());
3120 return $action;
3121 }
3122 }
3123
3124
3125} //end Gpf_Rpc_ActionRequest
3126
3127if (!class_exists('Gpf_Rpc_Action', false)) {
3128 class Gpf_Rpc_Action extends Gpf_Object implements Gpf_Rpc_Serializable {
3129 private $errorMessage = "";
3130 private $infoMessage = "";
3131 private $successCount = 0;
3132 private $errorCount = 0;
3133 private $isFinished = true;
3134 /**
3135 * @var Gpf_Rpc_Params
3136 */
3137 private $params;
3138
3139 const IDS = 'ids';
3140 const IDS_REQUEST = 'idsRequest';
3141
3142 public function __construct(Gpf_Rpc_Params $params, $infoMessage = '', $errorMessage = '') {
3143 $this->params = $params;
3144 $this->infoMessage = $infoMessage;
3145 $this->errorMessage = $errorMessage;
3146 }
3147
3148 /**
3149 * @return ArrayIterator|Gpf_View_GridService_IdsIterator
3150 * @throws Gpf_Exception
3151 */
3152 public function getIds() {
3153 if ($this->params->exists(self::IDS)) {
3154 return new ArrayIterator($this->params->get(self::IDS));
3155 }
3156 if ($this->params->exists(self::IDS_REQUEST)) {
3157 return $this->getRequestIdsIterator();
3158 }
3159 throw new Gpf_Exception('No ids selected');
3160 }
3161
3162 public function getParam($name) {
3163 return $this->params->get($name);
3164 }
3165
3166 public function existsParam($name) {
3167 return $this->params->exists($name);
3168 }
3169
3170 /**
3171 *
3172 * @return Gpf_Rpc_Params
3173 */
3174 public function getParams() {
3175 return $this->params;
3176 }
3177
3178 protected function getRequestIdsIterator() {
3179 $json = new Gpf_Rpc_Json();
3180 $requestParams = new Gpf_Rpc_Params($json->decode($this->params->get(self::IDS_REQUEST)));
3181 $c = $requestParams->getClass();
3182 $gridService = new $c;
3183 if(!($gridService instanceof Gpf_View_GridService)) {
3184 throw new Gpf_Exception(sprintf('%s is not Gpf_View_GridService class.', $requestParams->getClass()));
3185 }
3186 $requestParams->set('columns', array());
3187 return $gridService->getIdsIterator($requestParams);
3188 }
3189
3190 public function toObject() {
3191 $response = new stdClass();
3192 $response->success = Gpf::YES;
3193 $response->finished = $this->isFinished ? Gpf::YES : Gpf::NO;
3194
3195 $response->errorMessage = "";
3196 if ($this->errorCount > 0) {
3197 $response->success = "N";
3198 $response->errorMessage = $this->_($this->errorMessage, $this->errorCount);
3199 }
3200
3201 $response->infoMessage = "";
3202 if ($this->successCount > 0) {
3203 $response->infoMessage = $this->_($this->infoMessage, $this->successCount);
3204 }
3205
3206 return $response;
3207 }
3208
3209 public function setNotFinished() {
3210 $this->isFinished = false;
3211 }
3212
3213 public function loadFromObject(stdClass $object) {
3214 $this->errorMessage = $object->errorMessage;
3215 $this->infoMessage = $object->infoMessage;
3216
3217 if($object->success == Gpf::NO) {
3218 $this->addError();
3219 }
3220 }
3221
3222 public function isError() {
3223 return $this->errorCount > 0;
3224 }
3225
3226 public function toText() {
3227 if ($this->isError()) {
3228 return $this->_($this->errorMessage, $this->errorCount);
3229 } else {
3230 return $this->_($this->infoMessage, $this->successCount);
3231 }
3232 }
3233
3234 public function setErrorMessage($message) {
3235 $this->errorMessage = $message;
3236 }
3237
3238 public function getErrorMessage() {
3239 return $this->errorMessage;
3240 }
3241
3242 public function getInfoMessage() {
3243 return $this->infoMessage;
3244 }
3245
3246 public function setInfoMessage($message) {
3247 $this->infoMessage = $message;
3248 }
3249
3250 public function addOk($count = 1) {
3251 $this->successCount += $count;
3252 }
3253
3254 public function addError($count = 1) {
3255 $this->errorCount += $count;
3256 }
3257
3258 }
3259
3260
3261} //end Gpf_Rpc_Action
3262
3263if (!class_exists('Gpf_Rpc_Map', false)) {
3264 class Gpf_Rpc_Map extends Gpf_Object implements Gpf_Rpc_Serializable {
3265
3266 function __construct(array $array){
3267 $this->array = $array;
3268 }
3269
3270 public function toObject() {
3271 return $this->array;
3272 }
3273
3274 public function toText() {
3275 return var_dump($this->array);
3276 }
3277 }
3278
3279
3280} //end Gpf_Rpc_Map
3281
3282if (!class_exists('Gpf_Log', false)) {
3283 class Gpf_Log {
3284 const CRITICAL = 50;
3285 const ERROR = 40;
3286 const WARNING = 30;
3287 const INFO = 20;
3288 const DEBUG = 10;
3289
3290 /**
3291 * @var Gpf_Log_Logger
3292 */
3293 private static $logger;
3294
3295 /**
3296 * @return Gpf_Log_Logger
3297 */
3298 private static function getLogger() {
3299 if (self::$logger == null) {
3300 self::$logger = Gpf_Log_Logger::getInstance();
3301 }
3302 return self::$logger;
3303 }
3304
3305 private function __construct() {
3306 }
3307
3308 public static function disableType($type) {
3309 self::getLogger()->disableType($type);
3310 }
3311
3312 public static function enableAllTypes() {
3313 self::getLogger()->enableAllTypes();
3314 }
3315
3316 /**
3317 * logs message
3318 *
3319 * @param string $message
3320 * @param string $logLevel
3321 * @param string $logGroup
3322 */
3323 public static function log($message, $logLevel, $logGroup = null) {
3324 self::getLogger()->log($message, $logLevel, $logGroup);
3325 }
3326
3327 /**
3328 * logs debug message
3329 *
3330 * @param string $message
3331 * @param string $logGroup
3332 */
3333 public static function debug($message, $logGroup = null) {
3334 self::getLogger()->debug($message, $logGroup);
3335 }
3336
3337 /**
3338 * logs info message
3339 *
3340 * @param string $message
3341 * @param string $logGroup
3342 */
3343 public static function info($message, $logGroup = null) {
3344 self::getLogger()->info($message, $logGroup);
3345 }
3346
3347 /**
3348 * logs warning message
3349 *
3350 * @param string $message
3351 * @param string $logGroup
3352 */
3353 public static function warning($message, $logGroup = null) {
3354 self::getLogger()->warning($message, $logGroup);
3355 }
3356
3357 /**
3358 * logs error message
3359 *
3360 * @param string $message
3361 * @param string $logGroup
3362 */
3363 public static function error($message, $logGroup = null) {
3364 self::getLogger()->error($message, $logGroup);
3365 }
3366
3367 /**
3368 * logs critical error message
3369 *
3370 * @param string $message
3371 * @param string $logGroup
3372 */
3373 public static function critical($message, $logGroup = null) {
3374 self::getLogger()->critical($message, $logGroup);
3375 }
3376
3377 /**
3378 * Attach new log system
3379 *
3380 * @param string $type
3381 * Gpf_Log_LoggerDisplay::TYPE
3382 * Gpf_Log_LoggerFile::TYPE
3383 * Gpf_Log_LoggerDatabase::TYPE
3384 * @param string $logLevel
3385 * Gpf_Log::CRITICAL
3386 * Gpf_Log::ERROR
3387 * Gpf_Log::WARNING
3388 * Gpf_Log::INFO
3389 * Gpf_Log::DEBUG
3390 * @return Gpf_Log_LoggerBase
3391 */
3392 public static function addLogger($type, $logLevel) {
3393 if($type instanceof Gpf_Log_LoggerBase) {
3394 return self::getLogger()->addLogger($type, $logLevel);
3395 }
3396 return self::getLogger()->add($type, $logLevel);
3397 }
3398
3399 public static function removeAll() {
3400 self::getLogger()->removeAll();
3401 }
3402
3403 public static function isLogToDisplay() {
3404 return self::getLogger()->isLogToDisplay();
3405 }
3406 }
3407
3408} //end Gpf_Log
3409
3410if (!class_exists('Gpf_Log_Logger', false)) {
3411 class Gpf_Log_Logger extends Gpf_Object {
3412 /**
3413 * @var array
3414 */
3415 static private $instances = array();
3416 /**
3417 * @var array
3418 */
3419 private $loggers = array();
3420
3421 /**
3422 * array of custom parameters
3423 */
3424 private $customParameters = array();
3425
3426 private $disabledTypes = array();
3427
3428 private $group = null;
3429 private $type = null;
3430 private $logToDisplay = false;
3431
3432 /**
3433 * returns instance of logger class.
3434 * You can add instance name, if you want to have multiple independent instances of logger
3435 *
3436 * @param string $instanceName
3437 * @return Gpf_Log_Logger
3438 */
3439 public static function getInstance($instanceName = '_') {
3440 if($instanceName == '') {
3441 $instanceName = '_';
3442 }
3443
3444 if (!array_key_exists($instanceName, self::$instances)) {
3445 self::$instances[$instanceName] = new Gpf_Log_Logger();
3446 }
3447 $instance = self::$instances[$instanceName];
3448 return $instance;
3449 }
3450
3451 public static function isLoggerInsert($sqlString) {
3452 return strpos($sqlString, 'INSERT INTO ' . Gpf_Db_Table_Logs::getName()) !== false;
3453 }
3454
3455 /**
3456 * attachs new log system
3457 *
3458 * @param unknown_type $system
3459 * @return Gpf_Log_LoggerBase
3460 */
3461 public function add($type, $logLevel) {
3462 if($type == Gpf_Log_LoggerDisplay::TYPE) {
3463 $this->logToDisplay = true;
3464 }
3465 return $this->addLogger($this->create($type), $logLevel);
3466 }
3467
3468 /**
3469 * Checks if logger with te specified type was already initialized
3470 *
3471 * @param unknown_type $type
3472 * @return unknown
3473 */
3474 public function checkLoggerTypeExists($type) {
3475 if(array_key_exists($type, $this->loggers)) {
3476 return true;
3477 }
3478
3479 return false;
3480 }
3481
3482 /**
3483 * returns true if debugging writes log to display
3484 *
3485 * @return boolean
3486 */
3487 public function isLogToDisplay() {
3488 return $this->logToDisplay && !in_array(Gpf_Log_LoggerDisplay::TYPE, $this->disabledTypes);
3489 }
3490
3491 public function removeAll() {
3492 $this->loggers = array();
3493 $this->customParameters = array();
3494 $this->disabledTypes = array();
3495 $this->logToDisplay = false;
3496 $this->group = null;
3497 }
3498
3499 /**
3500 *
3501 * @param Gpf_Log_LoggerBase $logger
3502 * @param int $logLevel
3503 * @return Gpf_Log_LoggerBase
3504 */
3505 public function addLogger(Gpf_Log_LoggerBase $logger, $logLevel) {
3506 $this->enableType($logger->getType());
3507 if($logger->getType() == Gpf_Log_LoggerDisplay::TYPE) {
3508 $this->logToDisplay = true;
3509 }
3510 if(!$this->checkLoggerTypeExists($logger->getType())) {
3511 $logger->setLogLevel($logLevel);
3512 $this->loggers[$logger->getType()] = $logger;
3513 return $logger;
3514 } else {
3515 $ll = new Gpf_Log_LoggerDatabase();
3516 $existingLogger = $this->loggers[$logger->getType()];
3517 if($existingLogger->getLogLevel() > $logLevel) {
3518 $existingLogger->setLogLevel($logLevel);
3519 }
3520 return $existingLogger;
3521 }
3522 }
3523
3524 public function getGroup() {
3525 return $this->group;
3526 }
3527
3528 public function setGroup($group = null) {
3529 $this->group = $group;
3530 if($group === null) {
3531 $this->group = Gpf_Common_String::generateId(10);
3532 }
3533 }
3534
3535 public function setType($type) {
3536 $this->type = $type;
3537 }
3538
3539 /**
3540 * function sets custom parameter for the logger
3541 *
3542 * @param string $name
3543 * @param string $value
3544 */
3545 public function setCustomParameter($name, $value) {
3546 $this->customParameters[$name] = $value;
3547 }
3548
3549 /**
3550 * returns custom parameter
3551 *
3552 * @param string $name
3553 * @return string
3554 */
3555 public function getCustomParameter($name) {
3556 if(isset($this->customParameters[$name])) {
3557 return $this->customParameters[$name];
3558 }
3559 return '';
3560 }
3561
3562 /**
3563 * logs message
3564 *
3565 * @param string $message
3566 * @param string $logLevel
3567 * @param string $logGroup
3568 */
3569 public function log($message, $logLevel, $logGroup = null) {
3570 $time = time();
3571 $group = $logGroup;
3572 if($this->group !== null) {
3573 $group = $this->group;
3574 if($logGroup !== null) {
3575 $group .= ' ' . $logGroup;
3576 }
3577 }
3578
3579 $callingFile = $this->findLogFile();
3580 $file = $callingFile['file'];
3581 if(isset($callingFile['classVariables'])) {
3582 $file .= ' '.$callingFile['classVariables'];
3583 }
3584 $line = $callingFile['line'];
3585
3586 foreach ($this->loggers as $logger) {
3587 if(!in_array($logger->getType(), $this->disabledTypes)) {
3588 if ($logger->getType() == Gpf_Log_LoggerDatabase::TYPE) {
3589 $ip = Gpf_Http::getRemoteIp();
3590 } else {
3591 $ip = Gpf_Http::getRemoteIpFull();
3592 }
3593 if ($ip == '') {
3594 $ip = '127.0.0.1';
3595 }
3596 $logger->logMessage($time, $message, $logLevel, $group, $ip, $file, $line, $this->type);
3597 }
3598 }
3599 }
3600
3601 /**
3602 * logs debug message
3603 *
3604 * @param string $message
3605 * @param string $logGroup
3606 */
3607 public function debug($message, $logGroup = null) {
3608 $this->log($message, Gpf_Log::DEBUG, $logGroup);
3609 }
3610
3611 /**
3612 * logs info message
3613 *
3614 * @param string $message
3615 * @param string $logGroup
3616 */
3617 public function info($message, $logGroup = null) {
3618 $this->log($message, Gpf_Log::INFO, $logGroup);
3619 }
3620
3621 /**
3622 * logs warning message
3623 *
3624 * @param string $message
3625 * @param string $logGroup
3626 */
3627 public function warning($message, $logGroup = null) {
3628 $this->log($message, Gpf_Log::WARNING, $logGroup);
3629 }
3630
3631 /**
3632 * logs error message
3633 *
3634 * @param string $message
3635 * @param string $logGroup
3636 */
3637 public function error($message, $logGroup = null) {
3638 $this->log($message, Gpf_Log::ERROR, $logGroup);
3639 }
3640
3641 /**
3642 * logs critical error message
3643 *
3644 * @param string $message
3645 * @param string $logGroup
3646 */
3647 public function critical($message, $logGroup = null) {
3648 $this->log($message, Gpf_Log::CRITICAL, $logGroup);
3649 }
3650
3651 public function disableType($type) {
3652 $this->disabledTypes[$type] = $type;
3653 }
3654
3655 public function enableType($type) {
3656 if(in_array($type, $this->disabledTypes)) {
3657 unset($this->disabledTypes[$type]);
3658 }
3659 }
3660
3661 public function enableAllTypes() {
3662 $this->disabledTypes = array();
3663 }
3664
3665 /**
3666 *
3667 * @return Gpf_Log_LoggerBase
3668 */
3669 private function create($type) {
3670 switch($type) {
3671 case Gpf_Log_LoggerDisplay::TYPE:
3672 return new Gpf_Log_LoggerDisplay();
3673 case Gpf_Log_LoggerFile::TYPE:
3674 return new Gpf_Log_LoggerFile();
3675 case Gpf_Log_LoggerDatabase::TYPE:
3676 case 'db':
3677 return new Gpf_Log_LoggerDatabase();
3678 }
3679 throw new Gpf_Log_Exception("Log system '$type' does not exist");
3680 }
3681
3682 private function findLogFile() {
3683 $calls = debug_backtrace();
3684
3685 $foundObject = null;
3686
3687 // special handling for sql benchmarks
3688 if($this->sqlBenchmarkFound($calls)) {
3689 $foundObject = $this->findFileBySqlBenchmark();
3690 }
3691
3692 if($foundObject == null) {
3693 $foundObject = $this->findFileByCallingMethod($calls);
3694 }
3695 if($foundObject == null) {
3696 $foundObject = $this->findLatestObjectBeforeString("Logger.class.php");
3697 }
3698 if($foundObject == null) {
3699 $last = count($calls);
3700 $last -= 1;
3701 if($last <0) {
3702 $last = 0;
3703 }
3704
3705 $foundObject = $calls[$last];
3706 }
3707
3708 return $foundObject;
3709 }
3710
3711 private function sqlBenchmarkFound($calls) {
3712 foreach($calls as $obj) {
3713 if(isset($obj['function']) && $obj['function'] == "sqlBenchmarkEnd") {
3714 return true;
3715 }
3716 }
3717 return false;
3718 }
3719
3720 private function findFileBySqlBenchmark() {
3721 $foundFile = $this->findLatestObjectBeforeString("DbEngine");
3722 if($foundFile != null && is_object($foundFile['object'])) {
3723 $foundFile['classVariables'] = $this->getObjectVariables($foundFile['object']);
3724 }
3725 return $foundFile;
3726 }
3727
3728 private function getObjectVariables($object) {
3729 if(is_object($object)) {
3730 $class = get_class($object);
3731 $methods = get_class_methods($class);
3732 if(in_array("__toString", $methods)) {
3733 return $object->__toString();
3734 }
3735 }
3736 return '';
3737 }
3738
3739 private function findFileByCallingMethod($calls) {
3740 $functionNames = array('debug', 'info', 'warning', 'error', 'critical', 'log');
3741 $foundObject = null;
3742 foreach($functionNames as $name) {
3743 $foundObject = $this->findCallingFile($calls, $name);
3744 if($foundObject != null) {
3745 return $foundObject;
3746 }
3747 }
3748
3749 return null;
3750 }
3751
3752 private function findCallingFile($calls, $functionName) {
3753 $previousObject = null;
3754 $logMessage = null;
3755 foreach($calls as $obj) {
3756 if ($logMessage == null) {
3757 if (isset($obj['function']) && $obj['function'] == $functionName) {
3758 $previousObject = $obj;
3759 if (isset($obj['args']) && is_array($obj['args']) && isset($obj['args'][0])) {
3760 $logMessage = $obj['args'][0];
3761 }
3762 }
3763 } else {
3764 if (isset($obj['args']) && is_array($obj['args']) && isset($obj['args'][0]) && $logMessage == $obj['args'][0]) {
3765 $previousObject = $obj;
3766 } else {
3767 return $previousObject;
3768 }
3769 }
3770 }
3771 return $previousObject;
3772 }
3773
3774 private function findLatestObjectBeforeString($text) {
3775 $callsReversed = array_reverse( debug_backtrace() );
3776
3777 $lastObject = null;
3778 foreach($callsReversed as $obj) {
3779 if(!isset($obj['file'])) {
3780 continue;
3781 }
3782 $pos = strpos($obj['file'], $text);
3783 if($pos !== false && $lastObject != null) {
3784 return $lastObject;
3785 }
3786 $lastObject = $obj;
3787 }
3788 return null;
3789 }
3790 }
3791
3792} //end Gpf_Log_Logger
3793
3794if (!class_exists('Gpf_Api_IncompatibleVersionException', false)) {
3795 class Gpf_Api_IncompatibleVersionException extends Exception {
3796
3797 private $apiLink;
3798
3799 public function __construct($url) {
3800 $this->apiLink = str_replace('scripts/server.php', '', $url). 'merchants/#Api-Integration';
3801 parent::__construct('Version of API not corresponds to the Application version. Please <a href="' . $this->apiLink . '" target="_blank">download latest version of API</a>.', 0);
3802 }
3803
3804 public function getApiDownloadLink() {
3805 return $this->apiLink;
3806 }
3807
3808 }
3809
3810} //end Gpf_Api_IncompatibleVersionException
3811
3812if (!class_exists('Gpf_Api_Session', false)) {
3813 class Gpf_Api_Session extends Gpf_Object {
3814 const MERCHANT = 'M';
3815 const AFFILIATE = 'A';
3816
3817 const AUTHENTICATE_CLASS_NAME = 'Gpf_Api_AuthService';
3818 const AUTHENTICATE_METHOD_NAME = 'authenticate';
3819
3820 private $url;
3821 private $sessionId = '';
3822 private $debug = false;
3823 private $message = '';
3824 private $roleType = '';
3825
3826 public function __construct($url) {
3827 $this->url = $url;
3828 }
3829 /**
3830 *
3831 * @param $username
3832 * @param $password
3833 * @param $roleType Gpf_Api_Session::MERCHANT or Gpf_Api_Session::AFFILIATE
3834 * @param string $languageCode language code (e.g. en-US, de-DE, sk, cz, du, ...)
3835 * @return boolean true if user was successfully logged
3836 */
3837 public function login($username, $password, $roleType = self::MERCHANT, $languageCode = null, $twofactorToken = null) {
3838 return $this->authenticateRequest($username, $password, '', $roleType, $languageCode, $twofactorToken);
3839 }
3840
3841 /**
3842 *
3843 * @param $authtoken
3844 * @param $roleType Gpf_Api_Session::MERCHANT or Gpf_Api_Session::AFFILIATE
3845 * @param string $languageCode language code (e.g. en-US, de-DE, sk, cz, du, ...)
3846 * @return boolean true if user was successfully logged
3847 */
3848 public function loginWithAuthToken($authtoken, $roleType = self::MERCHANT, $languageCode = null) {
3849 return $this->authenticateRequest('', '', $authtoken, $roleType, $languageCode);
3850 }
3851
3852 /**
3853 *
3854 * @param $username
3855 * @param $password
3856 * @param $authtoken
3857 * @param $roleType Gpf_Api_Session::MERCHANT or Gpf_Api_Session::AFFILIATE
3858 * @param string $languageCode language code (e.g. en-US, de-DE, sk, cz, du, ...)
3859 * @return boolean true if user was successfully logged
3860 */
3861 private function authenticateRequest($username, $password, $authtoken, $roleType = self::MERCHANT, $languageCode = null, $twofactorToken = null) {
3862 $request = new Gpf_Rpc_FormRequest($this->getAuthenticateClassName(), self::AUTHENTICATE_METHOD_NAME, $this);
3863 $request->setUrl($this->url);
3864 if ($username != '' && $password != '') {
3865 $request->setField('username', $username);
3866 $request->setField('password', $password);
3867 } else {
3868 $request->setField('authToken', $authtoken);
3869 }
3870 if ($twofactorToken != '') {
3871 $request->setField('twofactor_token', $twofactorToken);
3872 }
3873 $request->setField('roleType', $roleType);
3874 $request->setField('isFromApi', Gpf::YES);
3875 $request->setField('apiVersion', self::getAPIVersion());
3876 if($languageCode != null) {
3877 $request->setField("language", $languageCode);
3878 }
3879
3880 $this->roleType = $roleType;
3881
3882 try {
3883 $request->sendNow();
3884 } catch(Exception $e) {
3885 $this->setMessage("Connection error: ".$e->getMessage());
3886 return false;
3887 }
3888
3889 $form = $request->getForm();
3890 $this->checkApiVersion($form);
3891
3892 $this->message = $form->getInfoMessage();
3893
3894 if ($form->isSuccessful()) {
3895 $this->setMessage($form->getInfoMessage());
3896 if ($form->existsField("S")) {
3897 $this->sessionId = $form->getFieldValue("S");
3898 return true;
3899 }
3900 } else {
3901 $this->setMessage($form->getErrorMessage());
3902 }
3903
3904 return false;
3905 }
3906
3907 /**
3908 * Get version of installed application
3909 *
3910 * @return string version of installed application
3911 */
3912 public function getAppVersion() {
3913 $request = new Gpf_Rpc_FormRequest($this->getAuthenticateClassName(), "getAppVersion", $this);
3914 $request->setUrl($this->url);
3915
3916 try {
3917 $request->sendNow();
3918 } catch(Exception $e) {
3919 $this->setMessage("Connection error: ".$e->getMessage());
3920 return false;
3921 }
3922
3923 $form = $request->getForm();
3924 return $form->getFieldValue('version');
3925 }
3926
3927
3928 public function getMessage() {
3929 return $this->message;
3930 }
3931
3932 private function setMessage($msg) {
3933 $this->message = $msg;
3934 }
3935
3936 public function getDebug() {
3937 return $this->debug;
3938 }
3939
3940 public function setDebug($debug = true) {
3941 $this->debug = $debug;
3942 }
3943
3944 public function getSessionId() {
3945 return $this->sessionId;
3946 }
3947
3948 public function setSessionId($sessionId, $roleType = self::MERCHANT) {
3949 $this->sessionId = $sessionId;
3950 $this->roleType = $roleType;
3951 }
3952
3953 public function getRoleType() {
3954 return $this->roleType;
3955 }
3956
3957 public function getUrl() {
3958 return $this->url;
3959 }
3960
3961 public function getUrlWithSessionInfo($url) {
3962 if (strpos($url, '?') === false) {
3963 return $url . '?S=' . $this->getSessionId();
3964 }
3965 return $url . '&S=' . $this->getSessionId();
3966 }
3967
3968 protected function getAuthenticateClassName() {
3969 return self::AUTHENTICATE_CLASS_NAME;
3970 }
3971
3972 /**
3973 * Check API version
3974 * (has to be protected because of Drupal integration)
3975 *
3976 * @param Gpf_Rpc_Form $form
3977 */
3978 protected function checkApiVersion(Gpf_Rpc_Form $form) {
3979 if ($form->getFieldValue('correspondsApi') === Gpf::NO) {
3980 $exception = new Gpf_Api_IncompatibleVersionException($this->url);
3981 trigger_error($exception->getMessage(), E_USER_NOTICE);
3982 }
3983 }
3984
3985 /**
3986 * @return String
3987 */
3988 public static function getAPIVersion($fileName = __FILE__) {
3989 return PAP_API_VERSION;
3990 }
3991 }
3992
3993} //end Gpf_Api_Session
3994
3995if (!class_exists('Gpf_Rpc_Json', false)) {
3996 class Gpf_Rpc_Json implements Gpf_Rpc_DataEncoder, Gpf_Rpc_DataDecoder {
3997 /**
3998 * Marker constant for Services_JSON::decode(), used to flag stack state
3999 */
4000 const SERVICES_JSON_SLICE = 1;
4001
4002 /**
4003 * Marker constant for Services_JSON::decode(), used to flag stack state
4004 */
4005 const SERVICES_JSON_IN_STR = 2;
4006
4007 /**
4008 * Marker constant for Services_JSON::decode(), used to flag stack state
4009 */
4010 const SERVICES_JSON_IN_ARR = 3;
4011
4012 /**
4013 * Marker constant for Services_JSON::decode(), used to flag stack state
4014 */
4015 const SERVICES_JSON_IN_OBJ = 4;
4016
4017 /**
4018 * Marker constant for Services_JSON::decode(), used to flag stack state
4019 */
4020 const SERVICES_JSON_IN_CMT = 5;
4021
4022 /**
4023 * Behavior switch for Services_JSON::decode()
4024 */
4025 const SERVICES_JSON_LOOSE_TYPE = 16;
4026
4027 /**
4028 * Behavior switch for Services_JSON::decode()
4029 */
4030 const SERVICES_JSON_SUPPRESS_ERRORS = 32;
4031
4032 /**
4033 * @var Gpf_Rpc_Json
4034 */
4035 private static $instance;
4036
4037 private $errorHandler;
4038
4039 /**
4040 * constructs a new JSON instance
4041 *
4042 * @param int $use object behavior flags; combine with boolean-OR
4043 *
4044 * possible values:
4045 * - SERVICES_JSON_LOOSE_TYPE: loose typing.
4046 * "{...}" syntax creates associative arrays
4047 * instead of objects in decode().
4048 * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
4049 * Values which can't be encoded (e.g. resources)
4050 * appear as NULL instead of throwing errors.
4051 * By default, a deeply-nested resource will
4052 * bubble up with an error, so all return values
4053 * from encode() should be checked with isError()
4054 */
4055 function __construct($use = 0)
4056 {
4057 $this->use = $use;
4058 }
4059
4060
4061
4062 /**
4063 * convert a string from one UTF-16 char to one UTF-8 char
4064 *
4065 * Normally should be handled by mb_convert_encoding, but
4066 * provides a slower PHP-only method for installations
4067 * that lack the multibye string extension.
4068 *
4069 * @param string $utf16 UTF-16 character
4070 * @return string UTF-8 character
4071 * @access private
4072 */
4073 function utf162utf8($utf16)
4074 {
4075 // oh please oh please oh please oh please oh please
4076 if(Gpf_Php::isFunctionEnabled('mb_convert_encoding')) {
4077 return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
4078 }
4079
4080 $bytes = (ord($utf16[0]) << 8) | ord($utf16[1]);
4081
4082 switch(true) {
4083 case ((0x7F & $bytes) == $bytes):
4084 // this case should never be reached, because we are in ASCII range
4085 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4086 return chr(0x7F & $bytes);
4087
4088 case (0x07FF & $bytes) == $bytes:
4089 // return a 2-byte UTF-8 character
4090 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4091 return chr(0xC0 | (($bytes >> 6) & 0x1F))
4092 . chr(0x80 | ($bytes & 0x3F));
4093
4094 case (0xFFFF & $bytes) == $bytes:
4095 // return a 3-byte UTF-8 character
4096 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4097 return chr(0xE0 | (($bytes >> 12) & 0x0F))
4098 . chr(0x80 | (($bytes >> 6) & 0x3F))
4099 . chr(0x80 | ($bytes & 0x3F));
4100 }
4101
4102 // ignoring UTF-32 for now, sorry
4103 return '';
4104 }
4105
4106 /**
4107 * convert a string from one UTF-8 char to one UTF-16 char
4108 *
4109 * Normally should be handled by mb_convert_encoding, but
4110 * provides a slower PHP-only method for installations
4111 * that lack the multibye string extension.
4112 *
4113 * @param string $utf8 UTF-8 character
4114 * @return string UTF-16 character
4115 * @access private
4116 */
4117 function utf82utf16($utf8)
4118 {
4119 // oh please oh please oh please oh please oh please
4120 if(Gpf_Php::isFunctionEnabled('mb_convert_encoding')) {
4121 return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
4122 }
4123
4124 switch(strlen($utf8)) {
4125 case 1:
4126 // this case should never be reached, because we are in ASCII range
4127 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4128 return $utf8;
4129
4130 case 2:
4131 // return a UTF-16 character from a 2-byte UTF-8 char
4132 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4133 return chr(0x07 & (ord($utf8[0]) >> 2))
4134 . chr((0xC0 & (ord($utf8[0]) << 6))
4135 | (0x3F & ord($utf8[1])));
4136
4137 case 3:
4138 // return a UTF-16 character from a 3-byte UTF-8 char
4139 // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4140 return chr((0xF0 & (ord($utf8[0]) << 4))
4141 | (0x0F & (ord($utf8[1]) >> 2)))
4142 . chr((0xC0 & (ord($utf8[1]) << 6))
4143 | (0x7F & ord($utf8[2])));
4144 }
4145
4146 // ignoring UTF-32 for now, sorry
4147 return '';
4148 }
4149
4150 public function encodeResponse(Gpf_Rpc_Serializable $response) {
4151 return $this->encode($response->toObject());
4152 }
4153
4154 /**
4155 * encodes an arbitrary variable into JSON format
4156 *
4157 * @param mixed $var any number, boolean, string, array, or object to be encoded.
4158 * see argument 1 to Services_JSON() above for array-parsing behavior.
4159 * if var is a strng, note that encode() always expects it
4160 * to be in ASCII or UTF-8 format!
4161 *
4162 * @return mixed JSON string representation of input var or an error if a problem occurs
4163 * @access public
4164 */
4165 public function encode($var, $options = null) {
4166 if ($this->isJsonEncodeEnabled()) {
4167 return @json_encode($var, $options);
4168 }
4169 switch (gettype($var)) {
4170 case 'boolean':
4171 return $var ? 'true' : 'false';
4172
4173 case 'NULL':
4174 return 'null';
4175
4176 case 'integer':
4177 return (int) $var;
4178
4179 case 'double':
4180 case 'float':
4181 return (float) $var;
4182
4183 case 'string':
4184 // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
4185 $ascii = '';
4186 $strlen_var = strlen($var);
4187
4188 /*
4189 * Iterate over every character in the string,
4190 * escaping with a slash or encoding to UTF-8 where necessary
4191 */
4192 for ($c = 0; $c < $strlen_var; ++$c) {
4193
4194 $ord_var_c = ord($var[$c]);
4195
4196 switch (true) {
4197 case $ord_var_c == 0x08:
4198 $ascii .= '\b';
4199 break;
4200 case $ord_var_c == 0x09:
4201 $ascii .= '\t';
4202 break;
4203 case $ord_var_c == 0x0A:
4204 $ascii .= '\n';
4205 break;
4206 case $ord_var_c == 0x0C:
4207 $ascii .= '\f';
4208 break;
4209 case $ord_var_c == 0x0D:
4210 $ascii .= '\r';
4211 break;
4212
4213 case $ord_var_c == 0x22:
4214 case $ord_var_c == 0x2F:
4215 case $ord_var_c == 0x5C:
4216 // double quote, slash, slosh
4217 if ($options == JSON_UNESCAPED_SLASHES && $ord_var_c == 0x2F) {
4218 $ascii .= $var[$c];
4219 } else {
4220 $ascii .= '\\'.$var[$c];
4221 }
4222 break;
4223
4224 case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
4225 // characters U-00000000 - U-0000007F (same as ASCII)
4226 $ascii .= $var[$c];
4227 break;
4228
4229 case (($ord_var_c & 0xE0) == 0xC0):
4230 // characters U-00000080 - U-000007FF, mask 1 1 0 X X X X X
4231 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4232 $char = pack('C*', $ord_var_c, ord($var[$c + 1]));
4233 $c += 1;
4234 $utf16 = $this->utf82utf16($char);
4235 $ascii .= sprintf('\u%04s', bin2hex($utf16));
4236 break;
4237
4238 case (($ord_var_c & 0xF0) == 0xE0):
4239 // characters U-00000800 - U-0000FFFF, mask 1 1 1 0 X X X X
4240 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4241 $char = pack('C*', $ord_var_c,
4242 ord($var[$c + 1]),
4243 ord($var[$c + 2]));
4244 $c += 2;
4245 $utf16 = $this->utf82utf16($char);
4246 $ascii .= sprintf('\u%04s', bin2hex($utf16));
4247 break;
4248
4249 case (($ord_var_c & 0xF8) == 0xF0):
4250 // characters U-00010000 - U-001FFFFF, mask 1 1 1 1 0 X X X
4251 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4252 $char = pack('C*', $ord_var_c,
4253 ord($var[$c + 1]),
4254 ord($var[$c + 2]),
4255 ord($var[$c + 3]));
4256 $c += 3;
4257 $utf16 = $this->utf82utf16($char);
4258 $ascii .= sprintf('\u%04s', bin2hex($utf16));
4259 break;
4260
4261 case (($ord_var_c & 0xFC) == 0xF8):
4262 // characters U-00200000 - U-03FFFFFF, mask 111110XX
4263 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4264 $char = pack('C*', $ord_var_c,
4265 ord($var[$c + 1]),
4266 ord($var[$c + 2]),
4267 ord($var[$c + 3]),
4268 ord($var[$c + 4]));
4269 $c += 4;
4270 $utf16 = $this->utf82utf16($char);
4271 $ascii .= sprintf('\u%04s', bin2hex($utf16));
4272 break;
4273
4274 case (($ord_var_c & 0xFE) == 0xFC):
4275 // characters U-04000000 - U-7FFFFFFF, mask 1111110X
4276 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4277 $char = pack('C*', $ord_var_c,
4278 ord($var[$c + 1]),
4279 ord($var[$c + 2]),
4280 ord($var[$c + 3]),
4281 ord($var[$c + 4]),
4282 ord($var[$c + 5]));
4283 $c += 5;
4284 $utf16 = $this->utf82utf16($char);
4285 $ascii .= sprintf('\u%04s', bin2hex($utf16));
4286 break;
4287 }
4288 }
4289
4290 return '"'.$ascii.'"';
4291
4292 case 'array':
4293 /*
4294 * As per JSON spec if any array key is not an integer
4295 * we must treat the the whole array as an object. We
4296 * also try to catch a sparsely populated associative
4297 * array with numeric keys here because some JS engines
4298 * will create an array with empty indexes up to
4299 * max_index which can cause memory issues and because
4300 * the keys, which may be relevant, will be remapped
4301 * otherwise.
4302 *
4303 * As per the ECMA and JSON specification an object may
4304 * have any string as a property. Unfortunately due to
4305 * a hole in the ECMA specification if the key is a
4306 * ECMA reserved word or starts with a digit the
4307 * parameter is only accessible using ECMAScript's
4308 * bracket notation.
4309 */
4310
4311 // treat as a JSON object
4312 if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
4313 $optionsArray = array();
4314 for ($i = 0; $i < count($var); $i++) {
4315 $optionsArray[] = $options;
4316 }
4317 $properties = array_map(array($this, 'name_value'), array_keys($var), array_values($var), $optionsArray);
4318
4319 foreach($properties as $property) {
4320 if(Gpf_Rpc_Json::isError($property)) {
4321 return $property;
4322 }
4323 }
4324
4325 return '{' . join(',', $properties) . '}';
4326 }
4327
4328 $optionsArray = array();
4329 for ($i = 0; $i < count($var); $i++) {
4330 $optionsArray[] = $options;
4331 }
4332
4333 // treat it like a regular array
4334 $elements = array_map(array($this, 'encode'), $var, $optionsArray);
4335
4336 foreach($elements as $element) {
4337 if(Gpf_Rpc_Json::isError($element)) {
4338 return $element;
4339 }
4340 }
4341
4342 return '[' . join(',', $elements) . ']';
4343
4344 case 'object':
4345 $vars = get_object_vars($var);
4346 $optionsArray = array();
4347 for ($i = 0; $i < count($vars); $i++) {
4348 $optionsArray[] = $options;
4349 }
4350 $properties = array_map(array($this, 'name_value'),
4351 array_keys($vars),
4352 array_values($vars),
4353 $optionsArray);
4354
4355 foreach($properties as $property) {
4356 if(Gpf_Rpc_Json::isError($property)) {
4357 return $property;
4358 }
4359 }
4360
4361 return '{' . join(',', $properties) . '}';
4362
4363 default:
4364 if ($this->use & self::SERVICES_JSON_SUPPRESS_ERRORS) {
4365 return 'null';
4366 }
4367 return new Gpf_Rpc_Json_Error(gettype($var)." can not be encoded as JSON string");
4368 }
4369 }
4370
4371 /**
4372 * array-walking function for use in generating JSON-formatted name-value pairs
4373 *
4374 * @param string $name name of key to use
4375 * @param mixed $value reference to an array element to be encoded
4376 *
4377 * @return string JSON-formatted name-value pair, like '"name":value'
4378 * @access private
4379 */
4380 function name_value($name, $value, $options = null)
4381 {
4382 $encoded_value = $this->encode($value, $options);
4383
4384 if(Gpf_Rpc_Json::isError($encoded_value)) {
4385 return $encoded_value;
4386 }
4387
4388 return $this->encode(strval($name), $options) . ':' . $encoded_value;
4389 }
4390
4391 /**
4392 * reduce a string by removing leading and trailing comments and whitespace
4393 *
4394 * @param $str string string value to strip of comments and whitespace
4395 *
4396 * @return string string value stripped of comments and whitespace
4397 * @access private
4398 */
4399 function reduce_string($str)
4400 {
4401 $str = preg_replace(array(
4402
4403 // eliminate single line comments in '// ...' form
4404 '#^\s*//(.+)$#m',
4405
4406 // eliminate multi-line comments in '/* ... */' form, at start of string
4407 '#^\s*/\*(.+)\*/#Us',
4408
4409 // eliminate multi-line comments in '/* ... */' form, at end of string
4410 '#/\*(.+)\*/\s*$#Us'
4411
4412 ), '', $str);
4413
4414 // eliminate extraneous space
4415 return trim($str);
4416 }
4417
4418 private function getErrorHandler() {
4419 if ($this->errorHandler == null) {
4420 $this->errorHandler = new Gpf_Rpc_PhpErrorHandler();
4421 }
4422 return $this->errorHandler;
4423 }
4424
4425 /**
4426 * decodes a JSON string into appropriate variable
4427 *
4428 * @param string $str JSON-formatted string
4429 *
4430 * @return mixed number, boolean, string, array, or object
4431 * corresponding to given JSON input string.
4432 * See argument 1 to Services_JSON() above for object-output behavior.
4433 * Note that decode() always returns strings
4434 * in ASCII or UTF-8 format!
4435 * @access public
4436 */
4437
4438 public function decode($str, $assoc = false) {
4439 if ($this->isJsonDecodeEnabled()) {
4440 $response = $this->getErrorHandler()->callMethod('json_decode', array($str, $assoc));
4441 return $response;
4442 }
4443 if ($assoc) {
4444 $this->use = self::SERVICES_JSON_LOOSE_TYPE;
4445 }
4446 $str = $this->reduce_string($str);
4447
4448 switch (strtolower($str)) {
4449 case 'true':
4450 return true;
4451
4452 case 'false':
4453 return false;
4454
4455 case 'null':
4456 return null;
4457
4458 default:
4459 $m = array();
4460
4461 if (is_numeric($str)) {
4462 // Lookie-loo, it's a number
4463
4464 // This would work on its own, but I'm trying to be
4465 // good about returning integers where appropriate:
4466 // return (float)$str;
4467
4468 // Return float or int, as appropriate
4469 return ((float)$str == (integer)$str)
4470 ? (integer)$str
4471 : (float)$str;
4472
4473 } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
4474 // STRINGS RETURNED IN UTF-8 FORMAT
4475 $delim = substr($str, 0, 1);
4476 $chrs = substr($str, 1, -1);
4477 $utf8 = '';
4478 $strlen_chrs = strlen($chrs);
4479
4480 for ($c = 0; $c < $strlen_chrs; ++$c) {
4481
4482 $substr_chrs_c_2 = substr($chrs, $c, 2);
4483 $ord_chrs_c = ord($chrs[$c]);
4484
4485 switch (true) {
4486 case $substr_chrs_c_2 == '\b':
4487 $utf8 .= chr(0x08);
4488 ++$c;
4489 break;
4490 case $substr_chrs_c_2 == '\t':
4491 $utf8 .= chr(0x09);
4492 ++$c;
4493 break;
4494 case $substr_chrs_c_2 == '\n':
4495 $utf8 .= chr(0x0A);
4496 ++$c;
4497 break;
4498 case $substr_chrs_c_2 == '\f':
4499 $utf8 .= chr(0x0C);
4500 ++$c;
4501 break;
4502 case $substr_chrs_c_2 == '\r':
4503 $utf8 .= chr(0x0D);
4504 ++$c;
4505 break;
4506
4507 case $substr_chrs_c_2 == '\\"':
4508 case $substr_chrs_c_2 == '\\\'':
4509 case $substr_chrs_c_2 == '\\\\':
4510 case $substr_chrs_c_2 == '\\/':
4511 if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
4512 ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
4513 $utf8 .= $chrs[++$c];
4514 }
4515 break;
4516
4517 case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
4518 // single, escaped unicode character
4519 $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
4520 . chr(hexdec(substr($chrs, ($c + 4), 2)));
4521 $utf8 .= $this->utf162utf8($utf16);
4522 $c += 5;
4523 break;
4524
4525 case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
4526 $utf8 .= $chrs[$c];
4527 break;
4528
4529 case ($ord_chrs_c & 0xE0) == 0xC0:
4530 // characters U-00000080 - U-000007FF, mask 1 1 0 X X X X X
4531 //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4532 $utf8 .= substr($chrs, $c, 2);
4533 ++$c;
4534 break;
4535
4536 case ($ord_chrs_c & 0xF0) == 0xE0:
4537 // characters U-00000800 - U-0000FFFF, mask 1 1 1 0 X X X X
4538 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4539 $utf8 .= substr($chrs, $c, 3);
4540 $c += 2;
4541 break;
4542
4543 case ($ord_chrs_c & 0xF8) == 0xF0:
4544 // characters U-00010000 - U-001FFFFF, mask 1 1 1 1 0 X X X
4545 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4546 $utf8 .= substr($chrs, $c, 4);
4547 $c += 3;
4548 break;
4549
4550 case ($ord_chrs_c & 0xFC) == 0xF8:
4551 // characters U-00200000 - U-03FFFFFF, mask 111110XX
4552 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4553 $utf8 .= substr($chrs, $c, 5);
4554 $c += 4;
4555 break;
4556
4557 case ($ord_chrs_c & 0xFE) == 0xFC:
4558 // characters U-04000000 - U-7FFFFFFF, mask 1111110X
4559 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
4560 $utf8 .= substr($chrs, $c, 6);
4561 $c += 5;
4562 break;
4563
4564 }
4565
4566 }
4567
4568 return $utf8;
4569
4570 } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
4571 // array, or object notation
4572
4573 if ($str[0] == '[') {
4574 $stk = array(self::SERVICES_JSON_IN_ARR);
4575 $arr = array();
4576 } else {
4577 if ($this->use & self::SERVICES_JSON_LOOSE_TYPE) {
4578 $stk = array(self::SERVICES_JSON_IN_OBJ);
4579 $obj = array();
4580 } else {
4581 $stk = array(self::SERVICES_JSON_IN_OBJ);
4582 $obj = new stdClass();
4583 }
4584 }
4585
4586 array_push($stk, array('what' => self::SERVICES_JSON_SLICE,
4587 'where' => 0,
4588 'delim' => false));
4589
4590 $chrs = substr($str, 1, -1);
4591 $chrs = $this->reduce_string($chrs);
4592
4593 if ($chrs == '') {
4594 if (reset($stk) == self::SERVICES_JSON_IN_ARR) {
4595 return $arr;
4596
4597 } else {
4598 return $obj;
4599
4600 }
4601 }
4602
4603 //print("\nparsing {$chrs}\n");
4604
4605 $strlen_chrs = strlen($chrs);
4606
4607 for ($c = 0; $c <= $strlen_chrs; ++$c) {
4608
4609 $top = end($stk);
4610 $substr_chrs_c_2 = substr($chrs, $c, 2);
4611
4612 if (($c == $strlen_chrs) || (($chrs[$c] == ',') && ($top['what'] == self::SERVICES_JSON_SLICE))) {
4613 // found a comma that is not inside a string, array, etc.,
4614 // OR we've reached the end of the character list
4615 $slice = substr($chrs, $top['where'], ($c - $top['where']));
4616 array_push($stk, array('what' => self::SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
4617 //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
4618
4619 if (reset($stk) == self::SERVICES_JSON_IN_ARR) {
4620 // we are in an array, so just push an element onto the stack
4621 array_push($arr, $this->decode($slice));
4622
4623 } elseif (reset($stk) == self::SERVICES_JSON_IN_OBJ) {
4624 // we are in an object, so figure
4625 // out the property name and set an
4626 // element in an associative array,
4627 // for now
4628 $parts = array();
4629
4630 if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
4631 // "name":value pair
4632 $key = $this->decode($parts[1]);
4633 $val = $this->decode($parts[2]);
4634
4635 if ($this->use & self::SERVICES_JSON_LOOSE_TYPE) {
4636 $obj[$key] = $val;
4637 } else {
4638 $obj->$key = $val;
4639 }
4640 } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
4641 // name:value pair, where name is unquoted
4642 $key = $parts[1];
4643 $val = $this->decode($parts[2]);
4644
4645 if ($this->use & self::SERVICES_JSON_LOOSE_TYPE) {
4646 $obj[$key] = $val;
4647 } else {
4648 $obj->$key = $val;
4649 }
4650 }
4651
4652 }
4653
4654 } elseif ((($chrs[$c] == '"') || ($chrs[$c] == "'")) && ($top['what'] != self::SERVICES_JSON_IN_STR)) {
4655 // found a quote, and we are not inside a string
4656 array_push($stk, array('what' => self::SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs[$c]));
4657 //print("Found start of string at {$c}\n");
4658
4659 } elseif (($chrs[$c] == $top['delim']) &&
4660 ($top['what'] == self::SERVICES_JSON_IN_STR) &&
4661 (($chrs[$c - 1] != '\\') ||
4662 ($chrs[$c - 1] == '\\' && $chrs[$c - 2] == '\\'))) {
4663 // found a quote, we're in a string, and it's not escaped
4664 array_pop($stk);
4665 //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
4666
4667 } elseif (($chrs[$c] == '[') &&
4668 in_array($top['what'], array(self::SERVICES_JSON_SLICE, self::SERVICES_JSON_IN_ARR, self::SERVICES_JSON_IN_OBJ))) {
4669 // found a left-bracket, and we are in an array, object, or slice
4670 array_push($stk, array('what' => self::SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
4671 //print("Found start of array at {$c}\n");
4672
4673 } elseif (($chrs[$c] == ']') && ($top['what'] == self::SERVICES_JSON_IN_ARR)) {
4674 // found a right-bracket, and we're in an array
4675 array_pop($stk);
4676 //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
4677
4678 } elseif (($chrs[$c] == '{') &&
4679 in_array($top['what'], array(self::SERVICES_JSON_SLICE, self::SERVICES_JSON_IN_ARR, self::SERVICES_JSON_IN_OBJ))) {
4680 // found a left-brace, and we are in an array, object, or slice
4681 array_push($stk, array('what' => self::SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
4682 //print("Found start of object at {$c}\n");
4683
4684 } elseif (($chrs[$c] == '}') && ($top['what'] == self::SERVICES_JSON_IN_OBJ)) {
4685 // found a right-brace, and we're in an object
4686 array_pop($stk);
4687 //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
4688
4689 } elseif (($substr_chrs_c_2 == '/*') &&
4690 in_array($top['what'], array(self::SERVICES_JSON_SLICE, self::SERVICES_JSON_IN_ARR, self::SERVICES_JSON_IN_OBJ))) {
4691 // found a comment start, and we are in an array, object, or slice
4692 array_push($stk, array('what' => self::SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
4693 $c++;
4694 //print("Found start of comment at {$c}\n");
4695
4696 } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == self::SERVICES_JSON_IN_CMT)) {
4697 // found a comment end, and we're in one now
4698 array_pop($stk);
4699 $c++;
4700
4701 for ($i = $top['where']; $i <= $c; ++$i)
4702 $chrs = substr_replace($chrs, ' ', $i, 1);
4703
4704 //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
4705
4706 }
4707
4708 }
4709
4710 if (reset($stk) == self::SERVICES_JSON_IN_ARR) {
4711 return $arr;
4712
4713 } elseif (reset($stk) == self::SERVICES_JSON_IN_OBJ) {
4714 return $obj;
4715
4716 }
4717
4718 }
4719 }
4720 }
4721
4722 protected function isJsonEncodeEnabled() {
4723 return Gpf_Php::isFunctionEnabled('json_encode');
4724 }
4725
4726 protected function isJsonDecodeEnabled() {
4727 return Gpf_Php::isFunctionEnabled('json_decode');
4728 }
4729
4730
4731 /**
4732 * @todo Ultimately, this should just call PEAR::isError()
4733 */
4734 function isError($data, $code = null)
4735 {
4736 if (is_object($data) &&
4737 (get_class($data) == 'Gpf_Rpc_Json_Error' || is_subclass_of($data, 'Gpf_Rpc_Json_Error'))) {
4738 return true;
4739 }
4740 return false;
4741 }
4742
4743 public static function encodeStatic($var, $options = null) {
4744 return self::getInstance()->encode($var, $options);
4745 }
4746
4747 public static function decodeStatic($var, $assoc = false) {
4748 return self::getInstance()->decode($var, $assoc);
4749 }
4750
4751 private static function getInstance() {
4752 if (self::$instance === null) {
4753 self::$instance = new self;
4754 }
4755 return self::$instance;
4756 }
4757 }
4758
4759 class Gpf_Rpc_Json_Error {
4760 private $message;
4761
4762 public function __construct($message) {
4763 $this->message = $message;
4764 }
4765 }
4766
4767
4768} //end Gpf_Rpc_Json
4769
4770if (!class_exists('Gpf_Rpc_JsonObject', false)) {
4771 class Gpf_Rpc_JsonObject extends Gpf_Object {
4772
4773 public function __construct($object = null) {
4774 if ($object != null) {
4775 $this->initFrom($object);
4776 }
4777 }
4778
4779 public function decode($string) {
4780 if ($string == null || $string == "") {
4781 throw new Gpf_Exception("Invalid format (".get_class($this).")");
4782 }
4783 $string = stripslashes($string);
4784 $json = new Gpf_Rpc_Json();
4785 $object = $json->decode($string);
4786 if (!is_object($object)) {
4787 throw new Gpf_Exception("Invalid format (".get_class($this).")");
4788 }
4789 $this->initFrom($object);
4790 }
4791
4792 private function initFrom($object) {
4793 $object_vars = get_object_vars($object);
4794 foreach ($object_vars as $name => $value) {
4795 if (property_exists($this, $name)) {
4796 $this->$name = $value;
4797 }
4798 }
4799 }
4800
4801 public function encode() {
4802 $json = new Gpf_Rpc_Json();
4803 return $json->encode($this);
4804 }
4805
4806 public function __toString() {
4807 return $this->encode();
4808 }
4809 }
4810
4811} //end Gpf_Rpc_JsonObject
4812
4813if (!class_exists('Pap_Api_Object', false)) {
4814 class Pap_Api_Object extends Gpf_Object {
4815 private $session;
4816 protected $class = '';
4817 private $message = '';
4818
4819 const FIELD_NAME = "name";
4820 const FIELD_VALUE = "value";
4821 const FIELD_ERROR = "error";
4822 const FIELD_VALUES = "values";
4823 const FIELD_OPERATOR = 'operator';
4824
4825 const OPERATOR_EQUALS = '=';
4826 const OPERATOR_LIKE = 'L';
4827
4828 /**
4829 * @var Gpf_Data_IndexedRecordSet
4830 */
4831 private $fields;
4832
4833 public function __construct(Gpf_Api_Session $session) {
4834 $this->session = $session;
4835 $this->fields = new Gpf_Data_IndexedRecordSet(self::FIELD_NAME);
4836
4837 $header = new Gpf_Data_RecordHeader();
4838 $header->add(self::FIELD_NAME);
4839 $header->add(self::FIELD_VALUE);
4840 $header->add(self::FIELD_VALUES);
4841 $header->add(self::FIELD_OPERATOR);
4842 $header->add(self::FIELD_ERROR);
4843
4844 $this->fields->setHeader($header);
4845 }
4846
4847 public function setField($name, $value, $operator = self::OPERATOR_EQUALS) {
4848 $record = $this->fields->createRecord($name);
4849 $record->set(self::FIELD_VALUE, $value);
4850 $record->set(self::FIELD_OPERATOR, $operator);
4851
4852 $this->fields->add($record);
4853 }
4854
4855 public function getField($name) {
4856 try {
4857 $record = $this->fields->getRecord($name);
4858 return $record->get(self::FIELD_VALUE);
4859 } catch(Exception $e) {
4860 return null;
4861 }
4862 }
4863
4864 public function addErrorMessages(Gpf_Data_IndexedRecordSet $fields) {
4865 foreach($fields as $field) {
4866 if($field->get(self::FIELD_ERROR) != '') {
4867 $this->message .= '<br>'.$field->get(self::FIELD_NAME).' - '.$field->get(self::FIELD_ERROR);
4868 }
4869 }
4870 }
4871
4872 public function setFields(Gpf_Data_IndexedRecordSet $fields) {
4873 foreach($fields as $field) {
4874 $this->setField($field->get(self::FIELD_NAME), $field->get(self::FIELD_VALUE));
4875 }
4876 }
4877
4878 public function getFields() {
4879 return $this->fields;
4880 }
4881
4882 public function getSession() {
4883 return $this->session;
4884 }
4885
4886 public function setSession($session) {
4887 $this->session = $session;
4888 }
4889
4890 public function getMessage() {
4891 return $this->message;
4892 }
4893
4894 protected function getPrimaryKey() {
4895 throw new Exception("You have to define method getPrimaryKey() in the extended class!");
4896 }
4897
4898 protected function getGridRequest() {
4899 throw new Exception("You have to define method getGridRequest() in the extended class!");
4900 }
4901
4902 protected function fillFieldsToGridRequest($request) {
4903 foreach($this->fields as $field) {
4904 if($field->get(self::FIELD_VALUE) != '') {
4905 $request->addFilter($field->get(self::FIELD_NAME), $field->get(self::FIELD_OPERATOR), $field->get(self::FIELD_VALUE));
4906 }
4907 }
4908 }
4909
4910 protected function getPrimaryKeyFromFields() {
4911 $request = $this->getGridRequest();
4912 if($request == null) {
4913 throw new Exception("You have to set ".$this->getPrimaryKey()." before calling load()!");
4914 }
4915
4916 $this->fillFieldsToGridRequest($request);
4917
4918 $request->setLimit(0, 1);
4919 $request->sendNow();
4920 $grid = $request->getGrid();
4921 if($grid->getTotalCount() == 0) {
4922 throw new Exception("No rows found!");
4923 }
4924 if($grid->getTotalCount() > 1) {
4925 throw new Exception("Too many rows found!");
4926 }
4927 $recordset = $grid->getRecordset();
4928
4929 foreach($recordset as $record) {
4930 $this->setField($this->getPrimaryKey(), $record->get($this->getPrimaryKey()));
4931 break;
4932 }
4933 }
4934
4935 protected function afterCallRequest() {
4936 }
4937
4938 private function primaryKeyIsDefined() {
4939 $field = $this->getField($this->getPrimaryKey());
4940 if($field == null || $field == '') {
4941 return false;
4942 }
4943 return true;
4944 }
4945
4946 /**
4947 * function checks if at least some field is filled
4948 * (we'll use that field as filter for the grid)
4949 *
4950 */
4951 private function someFieldIsFilled() {
4952 foreach($this->fields as $field) {
4953 if($field->get(self::FIELD_VALUE) != '') {
4954 return true;
4955 }
4956 }
4957
4958 return false;
4959 }
4960
4961 private function callRequest($method) {
4962 $this->message = '';
4963
4964 $request = new Gpf_Rpc_FormRequest($this->class, $method, $this->session);
4965 $this->beforeCallRequest($request);
4966 foreach($this->getFields() as $field) {
4967 if($field->get(self::FIELD_VALUE) !== null) {
4968 $request->setField($field->get(self::FIELD_NAME), $field->get(self::FIELD_VALUE));
4969 }
4970 }
4971
4972 try {
4973 $request->sendNow();
4974 } catch(Gpf_Exception $e) {
4975 if(strpos($e->getMessage(), 'Row does not exist') !== false) {
4976 throw new Exception("Row with this ID does not exist");
4977 }
4978 }
4979
4980 $form = $request->getForm();
4981 if($form->isError()) {
4982 $this->message = $form->getErrorMessage();
4983 $this->addErrorMessages($form->getFields());
4984 return false;
4985 } else {
4986 $this->message = $form->getInfoMessage();
4987 }
4988
4989 $this->setFields($form->getFields());
4990
4991 $this->afterCallRequest();
4992
4993 return true;
4994 }
4995
4996 /**
4997 * @throws Exception
4998 */
4999 public function load() {
5000 if(!$this->primaryKeyIsDefined()) {
5001 if($this->getGridRequest() == null) {
5002 throw new Exception("You have to set ".$this->getPrimaryKey()." before calling load()!");
5003 }
5004
5005 if(!$this->someFieldIsFilled()) {
5006 throw new Exception("You have to set at least one field before calling load()!");
5007 }
5008
5009 $this->getPrimaryKeyFromFields();
5010 }
5011
5012 $this->setField("Id", $this->getField($this->getPrimaryKey()));
5013
5014 return $this->callRequest("load");
5015 }
5016
5017 /**
5018 * @throws Exception
5019 */
5020 public function save() {
5021 if(!$this->primaryKeyIsDefined()) {
5022 throw new Exception("You have to set ".$this->getPrimaryKey()." before calling save()!");
5023 }
5024 $this->setField("Id", $this->getField($this->getPrimaryKey()));
5025
5026 return $this->callRequest("save");
5027 }
5028
5029 public function add() {
5030 $this->fillEmptyRecord();
5031
5032 return $this->callRequest("add");
5033 }
5034
5035 protected function fillEmptyRecord() {
5036 }
5037
5038 protected function beforeCallRequest(Gpf_Rpc_FormRequest $request) {
5039 }
5040 }
5041
5042} //end Pap_Api_Object
5043
5044if (!class_exists('Pap_Api_AffiliatesGrid', false)) {
5045 class Pap_Api_AffiliatesGrid extends Gpf_Rpc_GridRequest {
5046
5047 private $dataValues = null;
5048
5049 public function __construct(Gpf_Api_Session $session) {
5050 if($session->getRoleType() == Gpf_Api_Session::AFFILIATE) {
5051 throw new Exception("This class can be used only by merchant!");
5052 } else {
5053 parent::__construct("Pap_Merchants_User_TopAffiliatesGrid", "getRows", $session);
5054 }
5055 }
5056 }
5057
5058} //end Pap_Api_AffiliatesGrid
5059
5060if (!class_exists('Pap_Api_AffiliatesGridSimple', false)) {
5061 class Pap_Api_AffiliatesGridSimple extends Gpf_Rpc_GridRequest {
5062 private $dataValues = null;
5063
5064 public function __construct(Gpf_Api_Session $session) {
5065 if ($session->getRoleType() == Gpf_Api_Session::AFFILIATE) {
5066 throw new Exception('This class can be used only by merchant!');
5067 } else {
5068 parent::__construct('Pap_Merchants_User_AffiliatesGridSimple', 'getRows', $session);
5069 }
5070 }
5071 }
5072
5073} //end Pap_Api_AffiliatesGridSimple
5074
5075if (!class_exists('Pap_Api_BannersGrid', false)) {
5076 class Pap_Api_BannersGrid extends Gpf_Rpc_GridRequest {
5077
5078 public function __construct(Gpf_Api_Session $session) {
5079 if($session->getRoleType() == Gpf_Api_Session::AFFILIATE) {
5080 throw new Exception("This class can be used only by merchant!");
5081 } else {
5082 parent::__construct("Pap_Merchants_Banner_BannersGrid", "getRows", $session);
5083 }
5084 }
5085 }
5086
5087} //end Pap_Api_BannersGrid
5088
5089if (!class_exists('Pap_Api_Affiliate', false)) {
5090 class Pap_Api_Affiliate extends Pap_Api_Object {
5091
5092 private $dataValues = null;
5093
5094 const CLASS_NAME_AFFILIATE = 'Pap_Affiliates_Profile_PersonalDetailsForm';
5095 const CLASS_NAME_MERCHANT = 'Pap_Merchants_User_AffiliateForm';
5096
5097 public function __construct(Gpf_Api_Session $session) {
5098 parent::__construct($session);
5099 $this->initClass($session);
5100 }
5101
5102 protected function initClass(Gpf_Api_Session $session) {
5103 if($session->getRoleType() == Gpf_Api_Session::AFFILIATE) {
5104 $this->class = self::CLASS_NAME_AFFILIATE;
5105 } else {
5106 $this->class = self::CLASS_NAME_MERCHANT;
5107 }
5108 }
5109
5110 private function initDataFields() {
5111 if ($this->dataValues === null) {
5112 $this->getDataFields();
5113 }
5114 }
5115
5116 protected function getPrimaryKey() {
5117 return 'id';
5118 }
5119
5120 public function getUserid() { return $this->getField("userid"); }
5121 public function setUserid($value) {
5122 $this->setField("userid", $value);
5123 $this->setField("Id", $value);
5124 }
5125
5126 public function getRefid() { return $this->getField("refid"); }
5127
5128 public function setRefid($value, $operator = self::OPERATOR_EQUALS) {
5129 $this->setField('refid', $value, $operator);
5130 }
5131
5132 public function getStatus() { return $this->getField("rstatus"); }
5133 public function setStatus($value) { $this->setField("rstatus", $value); }
5134
5135 public function getMinimumPayout() { return $this->getField("minimumpayout"); }
5136 public function setMinimumPayout($value) { $this->setField("minimumpayout", $value); }
5137
5138 public function getPayoutOptionId() { return $this->getField("payoutoptionid"); }
5139 public function setPayoutOptionId($value) { $this->setField("payoutoptionid", $value); }
5140
5141 public function getNote() { return $this->getField("note"); }
5142 public function setNote($value) { $this->setField("note", $value); }
5143
5144 public function getPhoto() { return $this->getField("photo"); }
5145 public function setPhoto($value) { $this->setField("photo", $value); }
5146
5147 public function getAuthToken() { return $this->getField('authtoken'); }
5148
5149 public function getUsername() { return $this->getField("username"); }
5150
5151 public function setUsername($value, $operator = self::OPERATOR_EQUALS) {
5152 $this->setField('username', $value, $operator);
5153 }
5154
5155 public function getPassword() { return $this->getField("rpassword"); }
5156 public function setPassword($value) { $this->setField("rpassword", $value); }
5157
5158 public function getFirstname() { return $this->getField("firstname"); }
5159
5160 public function setFirstname($value, $operator = self::OPERATOR_EQUALS) {
5161 $this->setField('firstname', $value, $operator);
5162 }
5163
5164 public function getLastname() { return $this->getField("lastname"); }
5165
5166 public function setLastname($value, $operator = self::OPERATOR_EQUALS) {
5167 $this->setField('lastname', $value, $operator);
5168 }
5169
5170 public function getParentUserId() { return $this->getField("parentuserid"); }
5171 public function setParentUserId($value) { $this->setField("parentuserid", $value); }
5172
5173 public function getVisitorId() { return $this->getField("visitorId"); }
5174 public function setVisitorId($value) { $this->setField("visitorId", $value); }
5175
5176 public function getIp() { return $this->getField("ip"); }
5177 public function setIp($value) { $this->setField("ip", $value); }
5178
5179 public function getNotificationEmail() { return $this->getField("notificationemail"); }
5180 public function setNotificationEmail($value) { $this->setField("notificationemail", $value); }
5181
5182 public function getLanguage() { return $this->getField('lang'); }
5183 public function setLanguage($value) { $this->setField('lang', $value); }
5184
5185 public function disableSignupBonus() { $this->setField('createSignupComm', Gpf::NO); }
5186 public function disableReferralCommissions() { $this->setField('createReferralComm', Gpf::NO); }
5187
5188 public function getData($index) {
5189 $this->checkIndex($index);
5190 return $this->getField("data$index");
5191 }
5192 public function setData($index, $value, $operator = self::OPERATOR_EQUALS) {
5193 $this->checkIndex($index);
5194 $this->setField("data$index", $value, $operator);
5195 }
5196
5197 public function setPayoutOptionField($code, $value) {
5198 $this->setField($code, $value);
5199 }
5200
5201 public function getDataName($index) {
5202 $this->checkIndex($index);
5203 $dataField = "data$index";
5204
5205 $this->initDataFields();
5206
5207 if(!is_array($this->dataValues) || !isset($this->dataValues[$dataField])) {
5208 return '';
5209 }
5210
5211 return $this->dataValues[$dataField]['name'];
5212 }
5213
5214 public function getDataStatus($index) {
5215 $this->checkIndex($index);
5216 $dataField = "data$index";
5217
5218 $this->initDataFields();
5219
5220 if(!is_array($this->dataValues) || !isset($this->dataValues[$dataField])) {
5221 return 'U';
5222 }
5223
5224 return $this->dataValues[$dataField]['status'];
5225 }
5226
5227 private function checkIndex($index) {
5228 if(!is_numeric($index) || $index > 25 || $index < 1) {
5229 throw new Exception("Incorrect index '$index', it must be between 1 and 25");
5230 }
5231
5232 return true;
5233 }
5234
5235 protected function fillEmptyRecord() {
5236 $this->setField("userid", "");
5237 $this->setField("agreeWithTerms", Gpf::YES);
5238 }
5239
5240 /**
5241 * retrieves names and states of data1..data25 fields
5242 *
5243 */
5244 protected function getDataFields() {
5245 $request = new Gpf_Rpc_RecordsetRequest('Gpf_Db_Table_FormFields', 'getFields', $this->getSession());
5246 $request->addParam('formId', 'affiliateForm');
5247 $request->addParam('status', $this->getDataFieldStatuses());
5248
5249 try {
5250 $request->sendNow();
5251 } catch(Exception $e) {
5252 throw new Exception('Cannot load datafields. Error: '.$e->getMessage());
5253 }
5254
5255 $recordset = $request->getRecordSet();
5256 $this->dataValues = array();
5257 foreach($recordset as $record) {
5258 $this->dataValues[$record->get('code')]['name'] = $record->get("name");
5259 $this->dataValues[$record->get('code')]['status'] = $record->get("status");
5260 }
5261 }
5262
5263 public function sendConfirmationEmail() {
5264 if($this->getSession()->getRoleType() == Gpf_Api_Session::AFFILIATE) {
5265 throw new Exception('Insufficient privileges');
5266 }
5267 $params = new Gpf_Rpc_Params();
5268 $params->add('ids', array($this->getUserid()));
5269 return $this->sendActionRequest('Pap_Merchants_User_AffiliateForm', 'sendSignupConfirmation', $params);
5270 }
5271
5272 /**
5273 * @param $campaignID
5274 * @param $sendNotification
5275 */
5276 public function assignToPrivateCampaign($campaignID, $sendNotification = false) {
5277 if($this->getSession()->getRoleType() == Gpf_Api_Session::AFFILIATE) {
5278 throw new Exception('Insufficient privileges');
5279 }
5280 $params = new Gpf_Rpc_Params();
5281 $params->add('campaignId', $campaignID);
5282 $params->add('sendNotification', ($sendNotification ? Gpf::YES : Gpf::NO));
5283 $params->add('ids', array($this->getUserid()));
5284 return $this->sendActionRequest('Pap_Db_UserInCommissionGroup', 'addUsers', $params);
5285 }
5286
5287 protected function getGridRequest() {
5288 $gridRequest = new Pap_Api_AffiliatesGridSimple($this->getSession());
5289 $gridRequest->addParam('columns', new Gpf_Rpc_Array(array(array('id'))));
5290 return $gridRequest;
5291 }
5292
5293 protected function getDataFieldStatuses() {
5294 return 'M,O,P,R,S,W';
5295 }
5296
5297 private function sendActionRequest($className, $method, Gpf_Rpc_Params $params) {
5298 $request = new Gpf_Rpc_ActionRequest($className, $method, $this->getSession());
5299 $request->setParams($params);
5300 $request->sendNow();
5301 return $request->getResponseObject()->toObject();
5302 }
5303
5304 protected function beforeCallRequest(Gpf_Rpc_FormRequest $request) {
5305 $request->addParam('isFromApi', Gpf::YES);
5306 }
5307
5308 public function add() {
5309 if ($this->class == self::CLASS_NAME_AFFILIATE) {
5310 throw new Gpf_Exception('Not implemented');
5311 }
5312 return parent::add();
5313 }
5314 }
5315
5316} //end Pap_Api_Affiliate
5317
5318if (!class_exists('Pap_Api_AffiliateSignup', false)) {
5319 class Pap_Api_AffiliateSignup extends Pap_Api_Affiliate {
5320
5321 public function __construct(Gpf_Api_Session $session) {
5322 parent::__construct($session);
5323 }
5324
5325 protected function initClass(Gpf_Api_Session $session) {
5326 $this->class = 'Pap_Signup_AffiliateForm';
5327 }
5328
5329 protected function getDataFieldStatuses() {
5330 return 'M,O,S,W';
5331 }
5332
5333 public function sendConfirmationEmail() {
5334 throw new Gpf_Exception('Not implemented');
5335 }
5336
5337 public function assignToPrivateCampaign($campaignID, $sendNotification = false) {
5338 throw new Gpf_Exception('Not implemented');
5339 }
5340
5341 protected function getGridRequest() {
5342 throw new Gpf_Exception('Not implemented');
5343 }
5344
5345 public function save() {
5346 throw new Gpf_Exception('Not implemented');
5347 }
5348
5349 public function load() {
5350 throw new Gpf_Exception('Not implemented');
5351 }
5352
5353 protected function beforeCallRequest(Gpf_Rpc_FormRequest $request) {
5354 parent::beforeCallRequest($request);
5355 $request->addParam('initSession', Gpf::YES);
5356 }
5357 }
5358
5359} //end Pap_Api_AffiliateSignup
5360
5361if (!class_exists('Pap_Api_TransactionsGrid', false)) {
5362 class Pap_Api_TransactionsGrid extends Gpf_Rpc_GridRequest {
5363
5364 const REFUND_MERCHANT_NOTE = 'merchant_note';
5365 const REFUND_TYPE = 'status';
5366 const REFUND_FEE = 'fee';
5367 const TYPE_REFUND = 'R';
5368 const TYPE_CHARGEBACK = 'H';
5369
5370 private $dataValues = null;
5371
5372 public function __construct(Gpf_Api_Session $session) {
5373 if($session->getRoleType() == Gpf_Api_Session::AFFILIATE) {
5374 $className = "Pap_Affiliates_Reports_TransactionsGrid";
5375 } else {
5376 $className = "Pap_Merchants_Transaction_TransactionsGrid";
5377 }
5378 parent::__construct($className, "getRows", $session);
5379 }
5380
5381 public function refund($note = '', $fee = 0) {
5382 return $this->makeRefundChargeback(self::TYPE_REFUND, $note, $fee);
5383 }
5384
5385 public function chargeback($note = '', $fee = 0) {
5386 return $this->makeRefundChargeback(self::TYPE_CHARGEBACK, $note, $fee);
5387 }
5388
5389 private function makeRefundChargeback($type, $note, $fee) {
5390 if ($this->apiSessionObject->getRoleType() == Gpf_Api_Session::AFFILIATE) {
5391 throw new Exception("This method can be used only by merchant!");
5392 }
5393 if ($this->getFiltersParameter()->getCount() == 0) {
5394 throw new Exception("Refund / Chargeback in transactions grid is possible to make only with filters!");
5395 }
5396
5397 $request = new Gpf_Rpc_ActionRequest('Pap_Merchants_Transaction_TransactionsForm', 'makeRefundChargebackByParams', $this->apiSessionObject);
5398 $request->addParam('filters', $this->getFiltersParameter());
5399 $request->addParam(self::REFUND_MERCHANT_NOTE, $note);
5400 $request->addParam(self::REFUND_TYPE, $type);
5401 $request->addParam(self::REFUND_FEE, $fee);
5402
5403 $request->sendNow();
5404
5405 return $request->getAction();
5406 }
5407 }
5408
5409} //end Pap_Api_TransactionsGrid
5410
5411if (!class_exists('Pap_Api_Transaction', false)) {
5412 class Pap_Api_Transaction extends Pap_Api_Object {
5413
5414 const TRACKING_METHOD_MANUAL_COMMISSION = 'M';
5415
5416 private $dataValues = null;
5417 private $isTransIdChanged = false;
5418
5419 public function __construct(Gpf_Api_Session $session) {
5420 if($session->getRoleType() == Gpf_Api_Session::AFFILIATE) {
5421 throw new Exception("This class can be used only by merchant!");
5422 } else {
5423 $this->class = "Pap_Merchants_Transaction_TransactionsForm";
5424 }
5425
5426 parent::__construct($session);
5427 }
5428
5429 public function getTransid() { return $this->getField("transid"); }
5430 public function setTransid($value) {
5431 $this->setField("transid", $value);
5432 $this->setField("Id", $value);
5433 $this->isTransIdChanged = true;
5434 }
5435
5436 public function getType() { return $this->getField("rtype"); }
5437 public function setType($value) { $this->setField("rtype", $value); }
5438
5439 public function getStatus() { return $this->getField("rstatus"); }
5440 public function setStatus($value) { $this->setField("rstatus", $value); }
5441
5442 public function getMultiTierCreation() { return $this->getField("multiTier"); }
5443 public function setMultiTierCreation($value) { $this->setField("multiTier", $value); }
5444
5445 public function getUserid() { return $this->getField("userid"); }
5446 public function setUserid($value) { $this->setField("userid", $value); }
5447
5448 public function getBannerid() { return $this->getField("bannerid"); }
5449 public function setBannerid($value) { $this->setField("bannerid", $value); }
5450
5451 public function getParentBannerid() { return $this->getField("parentbannerid"); }
5452 public function setParentBannerid($value) { $this->setField("parentbannerid", $value); }
5453
5454 public function getCampaignid() { return $this->getField("campaignid"); }
5455 public function setCampaignid($value) { $this->setField("campaignid", $value); }
5456
5457 public function getCountryCode() { return $this->getField("countrycode"); }
5458 public function setCountryCode($value) { $this->setField("countrycode", $value); }
5459
5460 public function getDateInserted() { return $this->getField("dateinserted"); }
5461 public function setDateInserted($value, $operator = self::OPERATOR_EQUALS) {
5462 $this->setField("dateinserted", $value, $operator);
5463 }
5464
5465 public function getDateApproved() { return $this->getField("dateapproved"); }
5466 public function setDateApproved($value, $operator = self::OPERATOR_EQUALS) {
5467 $this->setField("dateapproved", $value, $operator);
5468 }
5469
5470 public function getPayoutStatus() { return $this->getField("payoutstatus"); }
5471 public function setPayoutStatus($value) { $this->setField("payoutstatus", $value); }
5472
5473 public function getPayoutHistoryId() { return $this->getField("payouthistoryid"); }
5474 public function setPayoutHistoryId($value, $operator = self::OPERATOR_EQUALS) {
5475 $this->setField("payouthistoryid", $value, $operator);
5476 }
5477
5478 public function getRefererUrl() { return $this->getField("refererurl"); }
5479 public function setRefererUrl($value, $operator = self::OPERATOR_EQUALS) {
5480 $this->setField("refererurl", $value, $operator);
5481 }
5482
5483 public function getIp() { return $this->getField("ip"); }
5484 public function setIp($value, $operator = self::OPERATOR_EQUALS) {
5485 $this->setField("ip", $value, $operator);
5486 }
5487
5488 public function getBrowser() { return $this->getField("browser"); }
5489 public function setBrowser($value, $operator = self::OPERATOR_EQUALS) {
5490 $this->setField("browser", $value, $operator);
5491 }
5492
5493 public function getCommission() { return $this->getField("commission"); }
5494 public function setCommission($value) { $this->setField("commission", $value); }
5495
5496 public function getOrderId() { return $this->getField("orderid"); }
5497 public function setOrderId($value, $operator = self::OPERATOR_EQUALS) {
5498 $this->setField("orderid", $value, $operator);
5499 }
5500
5501 public function getProductId() { return $this->getField("productid"); }
5502 public function setProductId($value, $operator = self::OPERATOR_EQUALS) {
5503 $this->setField("productid", $value, $operator);
5504 }
5505
5506 public function getTotalCost() { return $this->getField("totalcost"); }
5507 public function setTotalCost($value) { $this->setField("totalcost", $value); }
5508
5509 public function getRecurringCommid() { return $this->getField("recurringcommid"); }
5510 public function setRecurringCommid($value) { $this->setField("recurringcommid", $value); }
5511
5512 public function getFirstClickTime() { return $this->getField("firstclicktime"); }
5513 public function setFirstClickTime($value, $operator = self::OPERATOR_EQUALS) {
5514 $this->setField("firstclicktime", $value, $operator);
5515 }
5516
5517 public function getFirstClickReferer() { return $this->getField("firstclickreferer"); }
5518 public function setFirstClickReferer($value, $operator = self::OPERATOR_EQUALS) {
5519 $this->setField("firstclickreferer", $value, $operator);
5520 }
5521
5522 public function getFirstClickIp() { return $this->getField("firstclickip"); }
5523 public function setFirstClickIp($value, $operator = self::OPERATOR_EQUALS) {
5524 $this->setField("firstclickip", $value, $operator);
5525 }
5526
5527 public function getFirstClickData1() { return $this->getField("firstclickdata1"); }
5528 public function setFirstClickData1($value, $operator = self::OPERATOR_EQUALS) {
5529 $this->setField("firstclickdata1", $value, $operator);
5530 }
5531
5532 public function getFirstClickData2() { return $this->getField("firstclickdata2"); }
5533 public function setFirstClickData2($value, $operator = self::OPERATOR_EQUALS) {
5534 $this->setField("firstclickdata2", $value, $operator);
5535 }
5536
5537 public function getClickCount() { return $this->getField("clickcount"); }
5538 public function setClickCount($value) { $this->setField("clickcount", $value); }
5539
5540 public function getLastClickTime() { return $this->getField("lastclicktime"); }
5541 public function setLastClickTime($value, $operator = self::OPERATOR_EQUALS) {
5542 $this->setField("lastclicktime", $value, $operator);
5543 }
5544
5545 public function getLastClickReferer() { return $this->getField("lastclickreferer"); }
5546 public function setLastClickReferer($value, $operator = self::OPERATOR_EQUALS) {
5547 $this->setField("lastclickreferer", $value, $operator);
5548 }
5549
5550 public function getLastClickIp() { return $this->getField("lastclickip"); }
5551 public function setLastClickIp($value, $operator = self::OPERATOR_EQUALS) {
5552 $this->setField("lastclickip", $value, $operator);
5553 }
5554
5555 public function getLastClickData1() { return $this->getField("lastclickdata1"); }
5556 public function setLastClickData1($value, $operator = self::OPERATOR_EQUALS) {
5557 $this->setField("lastclickdata1", $value, $operator);
5558 }
5559
5560 public function getLastClickData2() { return $this->getField("lastclickdata2"); }
5561 public function setLastClickData2($value, $operator = self::OPERATOR_EQUALS) {
5562 $this->setField("lastclickdata2", $value, $operator);
5563 }
5564
5565 public function getTrackMethod() { return $this->getField("trackmethod"); }
5566 public function setTrackMethod($value) { $this->setField("trackmethod", $value); }
5567
5568 public function getOriginalCurrencyId() { return $this->getField("originalcurrencyid"); }
5569 public function setOriginalCurrencyId($value) { $this->setField("originalcurrencyid", $value); }
5570
5571 public function getOriginalCurrencyValue() { return $this->getField("originalcurrencyvalue"); }
5572 public function setOriginalCurrencyValue($value) { $this->setField("originalcurrencyvalue", $value); }
5573
5574 public function getOriginalCurrencyRate() { return $this->getField("originalcurrencyrate"); }
5575 public function setOriginalCurrencyRate($value) { $this->setField("originalcurrencyrate", $value); }
5576
5577 public function getTier() { return $this->getField("tier"); }
5578 public function setTier($value) { $this->setField("tier", $value); }
5579
5580 public function getSplit() { return $this->getField("split"); }
5581 public function setSplit($value) { $this->setField("split", $value); }
5582
5583 public function getChannel() { return $this->getField("channel"); }
5584 public function setChannel($value) { $this->setField("channel", $value); }
5585
5586 public function getCommTypeId() { return $this->getField("commtypeid"); }
5587 public function setCommTypeId($value) { $this->setField("commtypeid", $value); }
5588
5589 public function getMerchantNote() { return $this->getField("merchantnote"); }
5590 public function setMerchantNote($value, $operator = self::OPERATOR_EQUALS) {
5591 $this->setField("merchantnote", $value, $operator);
5592 }
5593
5594 public function getSystemNote() { return $this->getField("systemnote"); }
5595 public function setSystemNote($value, $operator = self::OPERATOR_EQUALS) {
5596 $this->setField("systemnote", $value, $operator);
5597 }
5598
5599 public function getParentTransactionId() { return $this->getField("parenttransid"); }
5600 public function setParentTransactionId($value) { $this->setField("parenttransid", $value); }
5601
5602 public function getData($index) {
5603 $this->checkIndex($index);
5604 return $this->getField("data$index");
5605 }
5606 public function setData($index, $value, $operator = self::OPERATOR_EQUALS) {
5607 $this->checkIndex($index);
5608 $this->setField("data$index", $value, $operator);
5609 }
5610
5611 /**
5612 * @param $note optional note that will be added to the refund/chargeback transaction
5613 * @param $fee that will be added to the refund/chargeback transaction
5614 * @return Gpf_Rpc_Action
5615 */
5616 public function chargeBack($note = '', $fee = 0, $refundMultiTier = false) {
5617 return $this->makeRefundChargeBack($note, 'H', $fee, $refundMultiTier);
5618 }
5619
5620 /**
5621 * @param $note optional note that will be added to the refund/chargeback transaction
5622 * @param $fee that will be added to the refund/chargeback transaction
5623 * @return Gpf_Rpc_Action
5624 */
5625 public function refund($note = '', $fee = 0, $refundMultiTier = false) {
5626 return $this->makeRefundChargeBack($note, 'R', $fee, $refundMultiTier);
5627 }
5628
5629 /**
5630 * @param $note optional note that will be added to the refund/chargeback transaction
5631 * @param $fee that will be added to the refund/chargeback transaction
5632 * @return Gpf_Rpc_Action
5633 */
5634 public function chargeBackByOrderId($note = '', $fee = 0) {
5635 return $this->makeRefundChargeBackByOrderId($note, 'H', $fee);
5636 }
5637
5638 /**
5639 * @param $note optional note that will be added to the refund/chargeback transaction
5640 * @param $fee that will be added to the refund/chargeback transaction
5641 * @return Gpf_Rpc_Action
5642 */
5643 public function refundByOrderId($note = '', $fee = 0) {
5644 return $this->makeRefundChargeBackByOrderId($note, 'R', $fee);
5645 }
5646
5647 /**
5648 * @return Gpf_Rpc_Action
5649 */
5650 private function makeRefundChargeBack($note, $type, $fee, $refundMultiTier) {
5651 if ($this->getTransid() == '') {
5652 throw new Gpf_Exception("No transaction ID. Call setTransid() or load transaction before calling refund/chargeback");
5653 }
5654 $request = new Gpf_Rpc_ActionRequest($this->class, 'makeRefundChargeback', $this->getSession());
5655 $request->addParam('merchant_note', $note);
5656 $request->addParam('refund_multitier', $refundMultiTier ? 'Y' : 'N');
5657 $request->addParam('status', $type);
5658 $request->addParam('ids', new Gpf_Rpc_Map(array($this->getTransid())));
5659 $request->addParam('fee', $fee);
5660 $request->sendNow();
5661 return $request->getAction();
5662 }
5663
5664 /**
5665 * @return Gpf_Rpc_Action
5666 */
5667 private function makeRefundChargeBackByOrderId($note, $type, $fee) {
5668 if ($this->getOrderId() == '') {
5669 throw new Gpf_Exception("Order Id is empty. Call setOrderId() or load transaction before calling refund/chargeback");
5670 }
5671 $request = new Gpf_Rpc_ActionRequest($this->class, 'makeRefundChargebackByParams', $this->getSession());
5672 $request->addParam('merchant_note', $note);
5673 $request->addParam('status', $type);
5674 $request->addParam('filters', new Gpf_Rpc_Array(array(array('orderid', Gpf_Data_Filter::EQUALS, $this->getOrderId()))));
5675 $request->addParam('fee', $fee);
5676 $request->sendNow();
5677 return $request->getAction();
5678 }
5679
5680 /**
5681 * @param $orderid order ID of transaction which will be approved
5682 * @param $note optional note that will be added to the transaction
5683 * @return Gpf_Rpc_Action
5684 */
5685 public function approveByOrderId($note = '') {
5686 return $this->changeStatusPerOrderId($note, 'A');
5687 }
5688
5689 /**
5690 * @param $orderid order ID of transaction which will be declined
5691 * @param $note optional note that will be added to the transaction
5692 * @return Gpf_Rpc_Action
5693 */
5694 public function declineByOrderId($note = '') {
5695 return $this->changeStatusPerOrderId($note, 'D');
5696 }
5697
5698 /**
5699 * @return Gpf_Rpc_Action
5700 */
5701 private function changeStatusPerOrderId($note, $type) {
5702 if ($this->getOrderId() == '') {
5703 throw new Gpf_Exception('Order ID cannot be empty!');
5704 }
5705 $request = new Gpf_Rpc_ActionRequest($this->class, 'changeStatusPerOrderId', $this->getSession());
5706 $request->addParam('merchant_note', $note);
5707 $request->addParam('status', $type);
5708 $request->addParam('orderid', $this->getOrderId());
5709 $request->sendNow();
5710 return $request->getAction();
5711 }
5712
5713
5714 private function checkIndex($index) {
5715 if(!is_numeric($index) || $index > 5 || $index < 1) {
5716 throw new Exception("Incorrect index '$index', it must be between 1 and 5");
5717 }
5718
5719 return true;
5720 }
5721
5722 protected function fillEmptyRecord() {
5723 if (!$this->isTransIdChanged) {
5724 $this->setTransid('');
5725 }
5726 if($this->getType() == '') {
5727 $this->setType('S');
5728 }
5729 if($this->getMultiTierCreation() == '') {
5730 $this->setMultiTierCreation('N');
5731 }
5732 if($this->getTrackMethod() == '') {
5733 $this->setTrackMethod(self::TRACKING_METHOD_MANUAL_COMMISSION);
5734 }
5735 }
5736
5737 protected function getPrimaryKey() {
5738 return "id";
5739 }
5740
5741 protected function getGridRequest() {
5742 return new Pap_Api_TransactionsGrid($this->getSession());
5743 }
5744
5745 public function load() {
5746 $result = parent::load();
5747 $this->isTransIdChanged = false;
5748 return $result;
5749 }
5750 }
5751
5752} //end Pap_Api_Transaction
5753
5754if (!class_exists('Pap_Tracking_Action_RequestActionObject', false)) {
5755 class Pap_Tracking_Action_RequestActionObject extends Gpf_Rpc_JsonObject {
5756 public $ac = ''; // actionCode
5757 public $t = ''; // totalCost
5758 public $f = ''; // fixedCost
5759 public $o = ''; // order ID
5760 public $p = ''; // product ID
5761 public $d1 = ''; // data1
5762 public $d2 = ''; // data2
5763 public $d3 = ''; // data3
5764 public $d4 = ''; // data4
5765 public $d5 = ''; // data5
5766 public $a = ''; // affiliate ID
5767 public $c = ''; // campaign ID
5768 public $b = ''; // banner ID
5769 public $ch = ''; // channel ID
5770 public $cc = ''; // custom commission
5771 public $ccfc = ''; // load next tiers from campaign
5772 public $s = ''; // status
5773 public $cr = ''; // currency
5774 public $cp = ''; // coupon code
5775 public $ts = ''; // time stamp
5776 public $dndc = ''; // do not delete cookies
5777
5778 public function __construct($object = null) {
5779 parent::__construct($object);
5780 }
5781
5782 public function getActionCode() {
5783 return $this->ac;
5784 }
5785
5786 public function getTotalCost() {
5787 return $this->t;
5788 }
5789
5790 public function getFixedCost() {
5791 return $this->f;
5792 }
5793
5794 public function getOrderId() {
5795 return $this->o;
5796 }
5797
5798 public function getProductId() {
5799 return $this->p;
5800 }
5801
5802 public function getData1() {
5803 return $this->d1;
5804 }
5805
5806 public function getData2() {
5807 return $this->d2;
5808 }
5809
5810 public function getData3() {
5811 return $this->d3;
5812 }
5813
5814 public function getData4() {
5815 return $this->d4;
5816 }
5817
5818 public function getData5() {
5819 return $this->d5;
5820 }
5821
5822 public function getData($i) {
5823 $dataVar = 'd'.$i;
5824 return $this->$dataVar;
5825 }
5826
5827 public function setData($i, $value) {
5828 $dataVar = 'd'.$i;
5829 $this->$dataVar = $value;
5830 }
5831
5832 public function getAffiliateId() {
5833 return $this->a;
5834 }
5835
5836 public function getCampaignId() {
5837 return $this->c;
5838 }
5839
5840 public function getBannerId() {
5841 return $this->b;
5842 }
5843
5844 public function getChannelId() {
5845 return $this->ch;
5846 }
5847
5848 public function getCustomCommission() {
5849 return $this->cc;
5850 }
5851
5852 public function getCustomCommissionNextTiersFromCampaign() {
5853 return $this->ccfc;
5854 }
5855
5856 public function getStatus() {
5857 return $this->s;
5858 }
5859
5860 public function getCurrency() {
5861 return $this->cr;
5862 }
5863
5864 public function getCouponCode() {
5865 return $this->cp;
5866 }
5867
5868 public function getTimeStamp() {
5869 return $this->ts;
5870 }
5871
5872 public function isDoNotDeleteCookies() {
5873 return $this->dndc == Gpf::YES;
5874 }
5875
5876 public function setActionCode($value) {
5877 $this->ac = $value;
5878 }
5879
5880 public function setTotalCost($value) {
5881 $this->t = $value;
5882 }
5883
5884 public function setFixedCost($value) {
5885 $this->f = $value;
5886 }
5887
5888 public function setOrderId($value) {
5889 $this->o = $value;
5890 }
5891
5892 public function setProductId($value) {
5893 $this->p = $value;
5894 }
5895
5896 public function setData1($value) {
5897 $this->d1 = $value;
5898 }
5899
5900 public function setData2($value) {
5901 $this->d2 = $value;
5902 }
5903
5904 public function setData3($value) {
5905 $this->d3 = $value;
5906 }
5907
5908 public function setData4($value) {
5909 $this->d4 = $value;
5910 }
5911
5912 public function setData5($value) {
5913 $this->d5 = $value;
5914 }
5915
5916 public function setAffiliateId($value) {
5917 $this->a = $value;
5918 }
5919
5920 public function setCampaignId($value) {
5921 $this->c = $value;
5922 }
5923
5924 public function setBannerId($value) {
5925 $this->b = $value;
5926 }
5927
5928 public function setChannelId($value) {
5929 $this->ch = $value;
5930 }
5931
5932 public function setCustomCommission($value) {
5933 $this->cc = $value;
5934 }
5935
5936 public function setCustomCommissionNextTiersFromCampaign($value) {
5937 $this->ccfc = $value;
5938 }
5939
5940 public function setStatus($value) {
5941 $this->s = $value;
5942 }
5943
5944 public function setCurrency($value) {
5945 $this->cr = $value;
5946 }
5947
5948 public function setCouponCode($value) {
5949 $this->cp = $value;
5950 }
5951
5952 public function setTimeStamp($value) {
5953 $this->ts = $value;
5954 }
5955
5956 public function doNotDeleteCookies() {
5957 $this->dndc = Gpf::YES;
5958 }
5959
5960 }
5961
5962} //end Pap_Tracking_Action_RequestActionObject
5963
5964if (!class_exists('Pap_Tracking_Request', false)) {
5965 class Pap_Tracking_Request extends Gpf_Object {
5966 const PARAM_CAMPAIGN_ID_SETTING_NAME = 'campaignId';
5967
5968 /* other action parameters */
5969 const PARAM_ACTION_DEBUG = 'PDebug';
5970 const PARAM_CALL_FROM_JAVASCRIPT = 'cjs';
5971
5972 /* Constant param names */
5973 const PARAM_LINK_STYLE = 'ls';
5974 const PARAM_REFERRERURL_NAME = 'refe';
5975
5976 /* Param setting names */
5977 const PARAM_DESTINATION_URL_SETTING_NAME = 'param_name_extra_data3';
5978 const PARAM_CHANNEL_DEFAULT = 'chan';
5979 const PARAM_CURRENCY = 'cur';
5980
5981 /* Forced parameter names */
5982 const PARAM_FORCED_AFFILIATE_ID = 'AffiliateID';
5983 const PARAM_FORCED_BANNER_ID = 'BannerID';
5984 const PARAM_FORCED_CAMPAIGN_ID = 'CampaignID';
5985 const PARAM_FORCED_CHANNEL_ID = 'Channel';
5986 const PARAM_FORCED_IP = 'Ip';
5987
5988 private $countryCode;
5989
5990 protected $request;
5991
5992 /**
5993 * @var Gpf_Log_Logger
5994 */
5995 protected $logger;
5996
5997 function __construct() {
5998 $this->request = array_change_key_case($_REQUEST, CASE_LOWER);
5999 }
6000
6001 public function parseUrl($url) {
6002 $this->request = array();
6003 if ($url === null || $url == '') {
6004 return;
6005 }
6006 $url = rtrim($url, '&').'&';
6007 $url = '?'.ltrim($url, '?');
6008 $parsedUrl = parse_url($url);
6009 if ($parsedUrl === false || !array_key_exists('query', $parsedUrl)) {
6010 return;
6011 }
6012 parse_str($parsedUrl['query'], $args);
6013 foreach ($args as $name => $value) {
6014 $this->setRequestParameter($name, $value);
6015 }
6016 }
6017
6018 public function getAffiliateId() {
6019 return $this->getRequestParameter(self::getAffiliateClickParamName());
6020 }
6021
6022 public function getForcedAffiliateId() {
6023 return $this->getRequestParameter(self::getForcedAffiliateParamName());
6024 }
6025
6026 public function getBannerId() {
6027 return $this->getRequestParameter(self::getBannerClickParamName());
6028 }
6029
6030 public function getForcedBannerId() {
6031 return $this->getRequestParameter(self::getForcedBannerParamName());
6032 }
6033
6034 /**
6035 * @return Pap_Common_User
6036 */
6037 public function getUser() {
6038 try {
6039 return Pap_Affiliates_User::loadFromId($this->getRequestParameter($this->getAffiliateClickParamName()));
6040 } catch (Gpf_Exception $e) {
6041 return null;
6042 }
6043 }
6044
6045 /**
6046 * @param string $id
6047 * @return string
6048 */
6049 public function getRawExtraData($i) {
6050 $extraDataParamName = $this->getSaleExtraDataParamName($i);
6051 if (!isset($this->request[$extraDataParamName])) {
6052 return '';
6053 }
6054 $str = preg_replace("/%u([0-9a-f]{3,4})/i", "&#x\\1;",urldecode($this->request[$extraDataParamName]));
6055 return html_entity_decode($str,null,'UTF-8');
6056 }
6057
6058 public function setRawExtraData($i, $value) {
6059 $extraDataParamName = $this->getSaleExtraDataParamName($i);
6060 $this->setRequestParameter($extraDataParamName, $value);
6061 }
6062
6063 /**
6064 * returns custom click link parameter data1
6065 * It first checks for forced parameter Data1 given as parameter to JS tracking code
6066 *
6067 * @return string
6068 */
6069 public function getClickData1() {
6070 $value = $this->getRequestParameter('pd1');
6071 if($value != '') {
6072 return $value;
6073 }
6074
6075 return $this->getRequestParameter(self::getClickData1ParamName());
6076 }
6077
6078 /**
6079 * returns custom click link parameter data2
6080 * It first checks for forcet parameter Data2 given as parameter to JS tracking code
6081 *
6082 * @return string
6083 */
6084 public function getClickData2() {
6085 $value = $this->getRequestParameter('pd2');
6086 if($value != '') {
6087 return $value;
6088 }
6089
6090 return $this->getRequestParameter(self::getClickData2ParamName());
6091 }
6092
6093 public static function getClickData1ParamName() {
6094 return Gpf_Settings::get(Pap_Settings::PARAM_NAME_EXTRA_DATA.'1');
6095 }
6096
6097 public static function getClickData2ParamName() {
6098 return Gpf_Settings::get(Pap_Settings::PARAM_NAME_EXTRA_DATA.'2');
6099 }
6100
6101 public function getRefererUrl() {
6102 $referrerurlParam = $this->getRequestParameter(self::PARAM_REFERRERURL_NAME);
6103 if ($referrerurlParam != '') {
6104 return self::decodeRefererUrl($referrerurlParam);
6105 }
6106 if (isset($_SERVER['HTTP_REFERER'])) {
6107 return self::decodeRefererUrl($_SERVER['HTTP_REFERER']);
6108 }
6109 return '';
6110 }
6111
6112 public function getIP() {
6113 if ($this->getForcedIp() !== '') {
6114 return $this->getForcedIp();
6115 }
6116 return Gpf_Http::getRemoteIp();
6117 }
6118
6119 public function getCountryCode() {
6120 if ($this->countryCode === null) {
6121 $context = new Gpf_Data_Record(
6122 array(Pap_Db_Table_RawImpressions::IP, Pap_Db_Table_Impressions::COUNTRYCODE), array($this->getIP(), ''));
6123 Gpf_Plugins_Engine::extensionPoint('Tracker.request.getCountryCode', $context);
6124 $this->countryCode = $context->get(Pap_Db_Table_Impressions::COUNTRYCODE);
6125 }
6126 return $this->countryCode;
6127 }
6128
6129 public function getLinkStyle() {
6130 $paramLinkStyle = $this->getRequestParameter(self::PARAM_LINK_STYLE);
6131 if ($paramLinkStyle !== '1') {
6132 return Pap_Tracking_ClickTracker::LINKMETHOD_REDIRECT;
6133 }
6134 return Pap_Tracking_ClickTracker::LINKMETHOD_URLPARAMETERS;
6135 }
6136
6137 /**
6138 * set logger
6139 *
6140 * @param Gpf_Log_Logger $logger
6141 */
6142 public function setLogger($logger) {
6143 $this->logger = $logger;
6144 }
6145
6146 protected function debug($msg) {
6147 if($this->logger != null) {
6148 $this->logger->debug($msg);
6149 }
6150 }
6151
6152 public function getRequestParameter($paramName, $returnString = true) {
6153 $paramName = strtolower($paramName);
6154 if (!isset($this->request[$paramName])) {
6155 return '';
6156 }
6157 if (!$returnString) {
6158 return $this->request[$paramName];
6159 }
6160
6161 if (is_array($this->request[$paramName])) {
6162 return '';
6163 }
6164 return Gpf_Common_String::convertToUtf8($this->request[$paramName]);
6165 }
6166
6167 public function setRequestParameter($paramName, $value) {
6168 $this->request[strtolower($paramName)] = $value;
6169 }
6170
6171 static public function getRotatorBannerParamName() {
6172 return Gpf_Settings::get(Pap_Settings::PARAM_NAME_ROTATOR_ID);
6173 }
6174
6175 static public function getSpecialDestinationUrlParamName() {
6176 return Gpf_Settings::get(Pap_Settings::PARAM_NAME_DESTINATION_URL);
6177 }
6178
6179 public function getRotatorBannerId() {
6180 return $this->getRequestParameter(self::getRotatorBannerParamName());
6181 }
6182
6183 public function getSaleExtraDataParamName($i) {
6184 return Gpf_Settings::get(Pap_Settings::PARAM_NAME_EXTRA_DATA).$i;
6185 }
6186
6187 static public function getExtraDataParamName($i) {
6188 return Gpf_Settings::get(Pap_Settings::PARAM_NAME_EXTRA_DATA.$i);
6189 }
6190
6191 public function getDebug() {
6192 if(isset($_GET[self::PARAM_ACTION_DEBUG])) {
6193 return strtoupper($_GET[self::PARAM_ACTION_DEBUG]);
6194 }
6195 return '';
6196 }
6197
6198 public function toString() {
6199 $params = '';
6200 foreach($this->request as $key => $value) {
6201 $params .= ($params != '' ? ", " : '').Gpf_Common_String::convertToUtf8($key).'='.Gpf_Common_String::convertToUtf8(print_r($value, true));
6202 }
6203 return $params;
6204 }
6205
6206 public function getRecognizedClickParameters() {
6207 $params = 'Debug='.$this->getDebug();
6208 $params .= ',Data1='.$this->getClickData1();
6209 $params .= ',Data2='.$this->getClickData2();
6210
6211 return $params;
6212 }
6213
6214 static public function getAffiliateClickParamName() {
6215 return Gpf_Settings::get(Pap_Settings::PARAM_NAME_USER_ID);
6216 }
6217
6218 static public function getBannerClickParamName() {
6219 $parameterName = trim(Gpf_Settings::get(Pap_Settings::PARAM_NAME_BANNER_ID));
6220 if($parameterName == '') {
6221 $mesage = Gpf_Lang::_('Banner ID parameter name is empty. Review URL parameter name settings');
6222 Gpf_Log::critical($mesage);
6223 throw new Gpf_Exception($mesage);
6224 }
6225 return $parameterName;
6226 }
6227
6228 static public function getChannelParamName() {
6229 return Pap_Tracking_Request::PARAM_CHANNEL_DEFAULT;
6230 }
6231
6232 public function getChannelId() {
6233 return $this->getRequestParameter(self::getChannelParamName());
6234 }
6235
6236 static public function getForcedAffiliateParamName() {
6237 return Pap_Tracking_Request::PARAM_FORCED_AFFILIATE_ID;
6238 }
6239
6240 static public function getForcedBannerParamName() {
6241 return Pap_Tracking_Request::PARAM_FORCED_BANNER_ID;
6242 }
6243
6244 public function getForcedCampaignId() {
6245 return $this->getRequestParameter(self::getForcedCampaignParamName());
6246 }
6247
6248 static public function getForcedCampaignParamName() {
6249 return Pap_Tracking_Request::PARAM_FORCED_CAMPAIGN_ID;
6250 }
6251
6252 public function getForcedChannelId() {
6253 return $this->getRequestParameter(Pap_Tracking_Request::PARAM_FORCED_CHANNEL_ID);
6254 }
6255
6256 public function getCampaignId() {
6257 return $this->getRequestParameter(self::getCampaignParamName());
6258 }
6259
6260 static public function getCampaignParamName() {
6261 $parameterName = trim(Gpf_Settings::get(Pap_Settings::PARAM_NAME_CAMPAIGN_ID));
6262 if($parameterName == '') {
6263 $mesage = Gpf_Lang::_('Campaign ID parameter name is empty. Review URL parameter name settings');
6264 Gpf_Log::critical($mesage);
6265 throw new Gpf_Exception($mesage);
6266 }
6267 return $parameterName;
6268 }
6269
6270 public function getCurrency() {
6271 return $this->getRequestParameter(self::PARAM_CURRENCY);
6272 }
6273
6274 /**
6275 * @deprecated used in CallBackTracker plugins only. should be moved to callback tracker
6276 */
6277 public function getPostParam($name) {
6278 if (!isset($_POST[$name])) {
6279 return '';
6280 }
6281 return $_POST[$name];
6282 }
6283
6284 /**
6285 * This function does escape http:// and https:// in url as mod_rewrite disables requests with ://
6286 *
6287 * @param $url
6288 * @return encoded url
6289 */
6290 public static function encodeRefererUrl($url) {
6291 $url = str_replace('http://', 'H_', $url);
6292 $url = str_replace('https://', 'S_', $url);
6293 return $url;
6294 }
6295
6296 /**
6297 * This function does decoded encoded url
6298 *
6299 * @param encoded $url
6300 * @return $url
6301 */
6302 public static function decodeRefererUrl($url) {
6303 if (substr($url, 0, 2) == 'H_') {
6304 return 'http://' . substr($url, 2);
6305 }
6306 if (substr($url, 0, 2) == 'S_') {
6307 return 'https://' . substr($url, 2);
6308 }
6309 return $url;
6310 }
6311
6312 private function getForcedIp() {
6313 return $this->getRequestParameter(self::PARAM_FORCED_IP);
6314 }
6315 }
6316
6317} //end Pap_Tracking_Request
6318
6319if (!class_exists('Pap_Api_Tracker', false)) {
6320 class Pap_Api_Tracker extends Gpf_Object {
6321
6322 /**
6323 * @var Gpf_Api_Session
6324 */
6325 private $session;
6326 private $trackingResponse;
6327 private $visitorId;
6328 private $accountId;
6329 private $ip;
6330 private $userAgent;
6331 private $paramNameUserId = 'a_aid';
6332 private $overwriteCookie = false;
6333 /**
6334 * @var array<Pap_Tracking_Action_RequestActionObject>
6335 */
6336 private $sales = array();
6337 const VISITOR_COOKIE_NAME = 'PAPVisitorId';
6338 const AFFILIATE_COOKIE_NAME = 'PAPAffiliateId';
6339
6340 const NOT_LOADED_YET = '-1';
6341 /**
6342 * @var Gpf_Rpc_Data
6343 */
6344 private $affiliate = self::NOT_LOADED_YET;
6345 /**
6346 * @var Gpf_Rpc_Data
6347 */
6348 private $campaign = self::NOT_LOADED_YET;
6349 /**
6350 * @var Gpf_Rpc_Data
6351 */
6352 private $channel = self::NOT_LOADED_YET;
6353
6354 /**
6355 * This class requires correctly initialized merchant session
6356 *
6357 * @param Gpf_Api_Session $session
6358 */
6359 public function __construct(Gpf_Api_Session $session) {
6360 if($session->getRoleType() == Gpf_Api_Session::AFFILIATE) {
6361 throw new Exception("This class can be used only by merchant!");
6362 }
6363 $this->session = $session;
6364 $this->visitorId = $this->getVisitorIdFromCookie();
6365 }
6366
6367 private function getVisitorIdFromCookie() {
6368 if (!isset($_COOKIE[self::VISITOR_COOKIE_NAME])) {
6369 return '';
6370 }
6371 return $_COOKIE[self::VISITOR_COOKIE_NAME];
6372 }
6373
6374 public function setVisitorId($visitorId) {
6375 $this->visitorId = $visitorId;
6376 }
6377
6378 public function getVisitorId() {
6379 return $this->visitorId;
6380 }
6381
6382 public function setAccountId($accountId) {
6383 $this->accountId = $accountId;
6384 }
6385
6386 public function setParamNameUserId($paramNameUserId) {
6387 $this->paramNameUserId = $paramNameUserId;
6388 }
6389
6390 public function setOverwriteCookie($overwriteCookie = true) {
6391 $this->overwriteCookie = $overwriteCookie;
6392 }
6393
6394 public function track() {
6395 if (count($this->sales) == 0) {
6396 $this->trackClickRequest();
6397 return;
6398 }
6399
6400 foreach ($this->sales as $sale) {
6401 $request = $this->createTrackRequest();
6402 $saleParams = Gpf_Rpc_Json::encodeStatic(array($sale));
6403 $request->addQueryParam('sale', $saleParams);
6404
6405 $request->setUrl($request->getUrl() . $request->getQuery());
6406 if ($this->session->getDebug()) {
6407 echo 'Tracking request: '.$request->getUrl();
6408 echo "<br>\n";
6409 }
6410 $this->executeTrackRequest($request);
6411 }
6412 }
6413
6414 /**
6415 *
6416 * @return Gpf_Net_Http_Request
6417 */
6418 private function createTrackRequest() {
6419 $request = new Gpf_Net_Http_Request();
6420 $request->setUrl(str_replace('server.php', 'track.php', $this->session->getUrl()));
6421 $request->setMethod('GET');
6422 $this->setQueryParams($request);
6423 if ($this->session->getDebug()) {
6424 $request->addQueryParam('PDebug', 'Y');
6425 }
6426 return $request;
6427 }
6428
6429 private function executeTrackRequest(Gpf_Net_Http_Request $request) {
6430 $response = $this->sendRequest($request);
6431 $this->trackingResponse = trim($response->getBody());
6432 if ($this->session->getDebug()) {
6433 echo 'Tracking response: '.$this->trackingResponse."<br>\n";
6434 }
6435 $this->parseResponse();
6436 $this->affiliate = self::NOT_LOADED_YET;
6437 }
6438
6439 private function trackClickRequest() {
6440 $request = $this->createTrackRequest();
6441
6442 $request->setUrl($request->getUrl() . $request->getQuery());
6443 if ($this->session->getDebug()) {
6444 echo 'Tracking request: '.$request->getUrl();
6445 }
6446 $this->executeTrackRequest($request);
6447 }
6448
6449 protected function setQueryParams(Gpf_Net_Http_Request $request) {
6450 $request->addQueryParam('visitorId', $this->visitorId);
6451 $request->addQueryParam('accountId', $this->accountId);
6452 $request->addQueryParam('url', Pap_Tracking_Request::encodeRefererUrl($this->getUrl()));
6453 $request->addQueryParam('referrer', Pap_Tracking_Request::encodeRefererUrl($this->getReferrerUrl()));
6454 $request->addQueryParam('tracking', '1');
6455 $request->addQueryParam('getParams', $this->getGetParams()->getQuery());
6456 $request->addQueryParam('ip', $this->getIp());
6457 $request->addQueryParam('useragent', $this->getUserAgent());
6458 }
6459
6460 public function setIp($value) {
6461 $this->ip = $value;
6462 }
6463
6464 protected function getIp() {
6465 if ($this->ip !== null) {
6466 return $this->ip;
6467 }
6468 return Gpf_Http::getRemoteIp();
6469 }
6470
6471 public function setUserAgent($value) {
6472 $this->userAgent = $value;
6473 }
6474
6475 protected function getUserAgent() {
6476 if ($this->userAgent !== null) {
6477 return $this->userAgent;
6478 }
6479 return Gpf_Http::getUserAgent();
6480 }
6481
6482 protected function sendRequest(Gpf_Net_Http_Request $request) {
6483 $client = new Gpf_Net_Http_Client();
6484 return $client->execute($request);
6485 }
6486
6487 public function saveCookies() {
6488 if ($this->trackingResponse == '') {
6489 return;
6490 }
6491 $this->includeJavascript();
6492 $this->saveCookiesByJavascript();
6493 $this->saveAffiliateCookie();
6494 }
6495
6496 public function save3rdPartyCookiesOnly($cookieDomainValidity = null) {
6497 if ($this->visitorId == null) {
6498 return;
6499 }
6500 $this->save3rdPartyCookie(self::VISITOR_COOKIE_NAME, $this->visitorId, time() + 31536000, true, $cookieDomainValidity);
6501 $this->saveAffiliateCookie($cookieDomainValidity);
6502 }
6503
6504 private function saveAffiliateCookie($cookieDomainValidity = null) {
6505 if (isset($_GET[$this->paramNameUserId]) && $_GET[$this->paramNameUserId] != '') {
6506 if ($this->overwriteCookie || !$this->existsAffiliateCookie()) {
6507 $this->save3rdPartyCookie(self::AFFILIATE_COOKIE_NAME, $_GET[$this->paramNameUserId], time() + 300, true, $cookieDomainValidity);
6508 }
6509 }
6510 }
6511
6512 /**
6513 * @return Gpf_Rpc_Data
6514 */
6515 public function getAffiliate() {
6516 return $this->getData($this->affiliate, 'getAffiliate', 'userid');
6517 }
6518
6519 /**
6520 * @return Gpf_Rpc_Data
6521 */
6522 public function getCampaign() {
6523 return $this->getData($this->campaign, 'getCampaign', 'campaignid');
6524 }
6525
6526 /**
6527 * @return Gpf_Rpc_Data
6528 */
6529 public function getChannel() {
6530 return $this->getData($this->channel, 'getChannel', 'channelid');
6531 }
6532
6533 private function getData(&$data, $method, $primaryKeyName) {
6534 if ($this->visitorId == '') {
6535 return null;
6536 }
6537 if ($data === self::NOT_LOADED_YET) {
6538 $request = new Gpf_Rpc_DataRequest('Pap_Tracking_Visit_SingleVisitorProcessor', $method, $this->session);
6539 $request->addParam('visitorId', $this->visitorId);
6540 $request->addParam('accountId', $this->accountId);
6541 if (isset($_GET[$this->paramNameUserId]) && $_GET[$this->paramNameUserId] != '') {
6542 $request->addParam('userId', $_GET[$this->paramNameUserId]);
6543 } else if ($this->existsAffiliateCookie()) {
6544 $request->addParam('userId', $_COOKIE[self::AFFILIATE_COOKIE_NAME]);
6545 } else if ($this->getTrackerAffiliateId() != '') {
6546 $request->addParam('userId', $this->getTrackerAffiliateId());
6547 }
6548 if ($this->session->getSessionId() == '') {
6549 $request->addParam('initSession', Gpf::YES);
6550 }
6551 $request->sendNow();
6552 $data = $request->getData();
6553 if (is_null($data->getValue($primaryKeyName))) {
6554 $data = null;
6555 }
6556 }
6557 return $data;
6558 }
6559
6560 private function existsAffiliateCookie() {
6561 return isset($_COOKIE[self::AFFILIATE_COOKIE_NAME]) && !is_array($_COOKIE[self::AFFILIATE_COOKIE_NAME]) && $_COOKIE[self::AFFILIATE_COOKIE_NAME] != '';
6562 }
6563
6564 protected function getTrackerAffiliateId() {
6565 return '';
6566 }
6567
6568 /**
6569 * Creates and returns new sale
6570 *
6571 * @return Pap_Tracking_ActionObject
6572 */
6573 public function createSale() {
6574 return $this->createAction('');
6575 }
6576
6577 /**
6578 * Creates and returns new action
6579 *
6580 * @param string $actionCode
6581 * @return Pap_Tracking_ActionObject
6582 */
6583 public function createAction($actionCode = '') {
6584 $sale = new Pap_Tracking_Action_RequestActionObject();
6585 $sale->setActionCode($actionCode);
6586 $this->sales[] = $sale;
6587 return $sale;
6588 }
6589
6590 protected function getSaleParams() {
6591 if (count($this->sales) == 0) {
6592 return '';
6593 }
6594 $json = new Gpf_Rpc_Json();
6595 return $json->encode($this->sales);
6596 }
6597
6598 /**
6599 * Parses track.php response. Response can be empty or setVisitor('4c5e2151b8856e55dbfeb247c22300Hg');
6600 */
6601 private function parseResponse() {
6602 if ($this->trackingResponse == '') {
6603 return;
6604 }
6605 if (!preg_match('/setVisitor\(\'([a-zA-Z0-9]+)\'\);/', $this->trackingResponse, $matches)) {
6606 return;
6607 }
6608 if ($matches[1] != '') {
6609 $this->visitorId = $matches[1];
6610 }
6611 }
6612
6613 private function includeJavascript() {
6614 $trackjsUrl = str_replace('server.php', 'trackjs.php', $this->session->getUrl());
6615 echo '<script id="pap_x2s6df8d" src="'.$trackjsUrl.'" type="text/javascript"></script>';
6616 }
6617
6618 private function saveCookiesByJavascript() {
6619 echo '<script type="text/javascript">'.$this->trackingResponse.'</script>';
6620 }
6621
6622 protected function getUrl() {
6623 if (array_key_exists('PATH_INFO', $_SERVER) && @$_SERVER['PATH_INFO'] != '') {
6624 $scriptName = str_replace('\\', '/', @$_SERVER['PATH_INFO']);
6625 } else {
6626 if (array_key_exists('SCRIPT_NAME', $_SERVER)) {
6627 $scriptName = str_replace('\\', '/', @$_SERVER['SCRIPT_NAME']);
6628 } else {
6629 $scriptName = '';
6630 }
6631 }
6632 $portString = '';
6633 if(isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] != 80
6634 && $_SERVER['SERVER_PORT'] != 443) {
6635 $portString = ':' . $_SERVER["SERVER_PORT"];
6636 }
6637 $protocol = 'http';
6638 if(Gpf_Http::isSSL()) {
6639 $protocol = 'https';
6640 }
6641 return $protocol . '://' . $this->getServerName() . $portString . $scriptName;
6642 }
6643
6644 private function getServerName() {
6645 if (isset($_SERVER["SERVER_NAME"])) {
6646 return $_SERVER["SERVER_NAME"];
6647 }
6648 return 'localhost';
6649 }
6650
6651 protected function getReferrerUrl() {
6652 if (array_key_exists('HTTP_REFERER', $_SERVER) && $_SERVER['HTTP_REFERER'] != '') {
6653 return $_SERVER['HTTP_REFERER'];
6654 }
6655 return '';
6656 }
6657
6658 /**
6659 * @return Gpf_Net_Http_Request
6660 */
6661 protected function getGetParams() {
6662 $getParams = new Gpf_Net_Http_Request();
6663 if (is_array($_GET) && count($_GET) > 0) {
6664 foreach ($_GET as $name => $value) {
6665 $getParams->addQueryParam($name, $value);
6666 }
6667 }
6668 return $getParams;
6669 }
6670
6671 protected function save3rdPartyCookie($name, $value, $expire, $overwrite, $cookieDomainValidity = null) {
6672 if (!$overwrite && isset($_COOKIE[$name]) && $_COOKIE[$name] != '') {
6673 return;
6674 }
6675 if ($cookieDomainValidity == null) {
6676 Gpf_Http::setCookie($name, $value, $expire, "/");
6677 } else {
6678 Gpf_Http::setCookie($name, $value, $expire, "/", $cookieDomainValidity);
6679 }
6680 }
6681
6682 }
6683
6684} //end Pap_Api_Tracker
6685
6686if (!class_exists('Pap_Api_SaleTracker', false)) {
6687 class Pap_Api_SaleTracker extends Pap_Api_Tracker {
6688
6689 /**
6690 * @param string $saleScriptUrl Url to sale.php script
6691 */
6692 public function __construct($saleScriptUrl, $debug = false) {
6693 $session = new Gpf_Api_Session(str_replace('sale.php', 'server.php', $saleScriptUrl));
6694 if ($debug) {
6695 $session->setDebug(true);
6696 }
6697 parent::__construct($session);
6698 }
6699
6700 /**
6701 * sets value of the cookie to be used
6702 *
6703 * @param string $value
6704 */
6705 public function setCookieValue($value) {
6706 $this->setVisitorId($value);
6707 }
6708
6709 /**
6710 * Registers all created sales
6711 */
6712 public function register() {
6713 $this->track();
6714 }
6715 }
6716
6717} //end Pap_Api_SaleTracker
6718
6719if (!class_exists('Pap_Api_ClickTracker', false)) {
6720 class Pap_Api_ClickTracker extends Pap_Api_Tracker {
6721
6722 private $affiliateId;
6723 private $bannerId;
6724 private $campaignId;
6725 private $data1;
6726 private $data2;
6727 private $channelId;
6728
6729 /**
6730 * This class requires correctly initialized merchant session
6731 * @param Gpf_Api_Session $session
6732 */
6733 public function __construct(Gpf_Api_Session $session) {
6734 parent::__construct($session);
6735 }
6736
6737 /**
6738 * Use this function if you want to explicitly specify affiliate which made the click
6739 *
6740 * @param $affiliateId
6741 */
6742 public function setAffiliateId($affiliateId) {
6743 $this->affiliateId = $affiliateId;
6744 }
6745
6746 /**
6747 * Use this function if you want to explicitly specify banner through which the click was made
6748 *
6749 * @param $bannerId
6750 */
6751 public function setBannerId($bannerId) {
6752 $this->bannerId = $bannerId;
6753 }
6754
6755 /**
6756 * Use this function if you want to explicitly specify campaign for this click
6757 *
6758 * @param $campaignId
6759 */
6760 public function setCampaignID($campaignId) {
6761 $this->campaignId = $campaignId;
6762 }
6763
6764 public function setData1($data1) {
6765 $this->data1 = $data1;
6766 }
6767
6768 public function setData2($data2) {
6769 $this->data2 = $data2;
6770 }
6771
6772 /**
6773 * Use this function if you want to explicitly specify channel through which this click was made
6774 *
6775 * @param $bannerId
6776 */
6777 public function setChannel($channelId) {
6778 $this->channelId = $channelId;
6779 }
6780
6781 /**
6782 * @return Gpf_Net_Http_Request
6783 */
6784 protected function getGetParams() {
6785 $getParams = parent::getGetParams();
6786 if ($this->affiliateId != '') {
6787 $getParams->addQueryParam('AffiliateID', $this->affiliateId);
6788 }
6789 if ($this->bannerId != '') {
6790 $getParams->addQueryParam('BannerID', $this->bannerId);
6791 }
6792 if ($this->campaignId != '') {
6793 $getParams->addQueryParam('CampaignID', $this->campaignId);
6794 }
6795 if ($this->channelId != '') {
6796 $getParams->addQueryParam('chan', $this->channelId);
6797 }
6798 if ($this->data1 != '') {
6799 $getParams->addQueryParam('pd1', $this->data1);
6800 }
6801 if ($this->data2 != '') {
6802 $getParams->addQueryParam('pd2', $this->data2);
6803 }
6804 return $getParams;
6805 }
6806
6807 protected function getTrackerAffiliateId() {
6808 if ($this->affiliateId != '') {
6809 return $this->affiliateId;
6810 }
6811 return '';
6812 }
6813 }
6814
6815} //end Pap_Api_ClickTracker
6816
6817if (!class_exists('Pap_Api_RecurringCommission', false)) {
6818 class Pap_Api_RecurringCommission extends Pap_Api_Object {
6819
6820 public function __construct(Gpf_Api_Session $session) {
6821 parent::__construct($session);
6822 $this->class = 'Pap_Features_RecurringCommissions_RecurringCommissionsForm';
6823 }
6824
6825 public function setOrderId($value, $operator = self::OPERATOR_EQUALS) {
6826 $this->setField('orderid', $value, $operator);
6827 }
6828
6829 public function setTotalCost($value) {
6830 $this->setField('totalcost', $value);
6831 }
6832
6833 public function setCurrency($value) {
6834 $this->setField('currency', $value);
6835 }
6836
6837 public function getId() {
6838 return $this->getField('recurringcommissionid');
6839 }
6840
6841 protected function getPrimaryKey() {
6842 return "id";
6843 }
6844
6845 protected function getGridRequest() {
6846 return new Pap_Api_RecurringCommissionsGrid($this->getSession());
6847 }
6848
6849 public function createCommissions() {
6850 $request = new Gpf_Rpc_ActionRequest('Pap_Features_RecurringCommissions_RecurringCommissionsForm',
6851 'createCommissions', $this->getSession());
6852 $request->addParam('id', $this->getId());
6853 $request->addParam('orderid', $this->getField('orderid'));
6854 $request->addParam('totalcost', $this->getField('totalcost'));
6855 $request->addParam('currency', $this->getField('currency'));
6856 if ($this->getSession()->getSessionId() == '') {
6857 $request->addParam('initSession', Gpf::YES);
6858 }
6859 $request->sendNow();
6860 $action = $request->getAction();
6861 if ($action->isError()) {
6862 throw new Gpf_Exception($action->getErrorMessage());
6863 }
6864 }
6865
6866 public function createCommissionsReturnIds() {
6867 $request = new Gpf_Rpc_DataRequest('Pap_Features_RecurringCommissions_RecurringCommissionsForm',
6868 'createCommissionsReturnIds', $this->getSession());
6869 $request->addParam('id', $this->getId());
6870 $request->addParam('orderid', $this->getField('orderid'));
6871 $request->addParam('totalcost', $this->getField('totalcost'));
6872 $request->addParam('currency', $this->getField('currency'));
6873 if ($this->getSession()->getSessionId() == '') {
6874 $request->addParam('initSession', Gpf::YES);
6875 }
6876 $request->sendNow();
6877 return $request->getData()->getValue(Gpf_Rpc_Action::IDS);
6878 }
6879 }
6880
6881} //end Pap_Api_RecurringCommission
6882
6883if (!class_exists('Pap_Api_RecurringCommissionsGrid', false)) {
6884 class Pap_Api_RecurringCommissionsGrid extends Gpf_Rpc_GridRequest {
6885
6886 private $dataValues = null;
6887
6888 public function __construct(Gpf_Api_Session $session) {
6889 if($session->getRoleType() == Gpf_Api_Session::AFFILIATE) {
6890 throw new Exception("This class can be used only by merchant!");
6891 } else {
6892 parent::__construct("Pap_Features_RecurringCommissions_RecurringCommissionsGrid", "getRows", $session);
6893 }
6894 }
6895 }
6896
6897} //end Pap_Api_RecurringCommissionsGrid
6898
6899if (!class_exists('Pap_Api_PayoutsGrid', false)) {
6900 class Pap_Api_PayoutsGrid extends Gpf_Rpc_GridRequest {
6901
6902 const PAP_MERCHANTS_PAYOUT_PAYAFFILIATESFORM_SUCCESS = 'success';
6903
6904 private $affiliatesToPay = array();
6905
6906 public function __construct(Gpf_Api_Session $session) {
6907 if($session->getRoleType() == Gpf_Api_Session::AFFILIATE) {
6908 throw new Gpf_Exception('Only merchant can view payouts grid. Please login as merchant.');
6909 }
6910
6911 $className = 'Pap_Merchants_Payout_PayAffiliatesGrid';
6912 parent::__construct($className, 'getRows', $session);
6913 }
6914
6915 public function payAffiliates($paymentNote = '', $affiliateNote = '', $send_payment_to_affiliate = Gpf::NO, $send_generated_invoices_to_merchant = Gpf::NO, $send_generated_invoices_to_affiliates = Gpf::NO) {
6916 $this->checkMerchantRole();
6917 if (count($this->getAffiliatesToPay()) == 0) {
6918 throw new Gpf_Exception('You must select at least one affiliate to pay.');
6919 }
6920 try {
6921 $this->sendPayTransactionsCall($paymentNote, $affiliateNote, $send_payment_to_affiliate, $send_generated_invoices_to_merchant, $send_generated_invoices_to_affiliates);
6922 } catch (Gpf_Exception $e) {
6923 throw new Gpf_Exception('Error during paying affiliates: ' . $e->getMessage());
6924 }
6925 }
6926
6927 protected function sendPayTransactionsCall($paymentNote, $affiliateNote, $send_payment_to_affiliate, $send_generated_invoices_to_merchant, $send_generated_invoices_to_affiliates) {
6928 $request = new Gpf_Rpc_ActionRequest('Pap_Merchants_Payout_PayAffiliatesForm', 'payAffiliates', $this->apiSessionObject);
6929 $request->addParam('paymentNote', $paymentNote);
6930 $request->addParam('affiliateNote', $affiliateNote);
6931 $request->addParam('send_payment_to_affiliate', $send_payment_to_affiliate);
6932 $request->addParam('send_generated_invoices_to_merchant', $send_generated_invoices_to_merchant);
6933 $request->addParam('send_generated_invoices_to_affiliates', $send_generated_invoices_to_affiliates);
6934 $request->addParam('ids', new Gpf_Rpc_Array($this->getAffiliatesToPay()));
6935 $request->addParam('filters', new Gpf_Rpc_Array($this->getFilters()));
6936 $request->sendNow();
6937
6938 if ($request->getResponseError() != '') {
6939 throw new Gpf_Exception($request->getResponseError());
6940 }
6941 $response = $request->getStdResponse();
6942
6943 if ($response->success == 'Y' && strpos($response->infoMessage, self::PAP_MERCHANTS_PAYOUT_PAYAFFILIATESFORM_SUCCESS) !== 0 ) {
6944 $request->sendNow();
6945 }
6946 }
6947
6948 public function addAllAffiliatesToPay() {
6949 $this->checkMerchantRole();
6950 try {
6951 $grid = $this->getGrid();
6952 $recordset = $grid->getRecordset();
6953 foreach($recordset as $rec) {
6954 $this->addAffiliateToPay($rec->get('id'));
6955 }
6956 } catch (Gpf_Exception $e) {
6957 throw new Gpf_Exception('You must load list of affiliates first!');
6958 }
6959 }
6960
6961 public function addAffiliateToPay($affiliateId) {
6962 if(!in_array($affiliateId, $this->affiliatesToPay)) {
6963 $this->affiliatesToPay[] = $affiliateId;
6964 }
6965 }
6966
6967 public function getAffiliatesToPay() {
6968 return $this->affiliatesToPay;
6969 }
6970
6971 private function checkMerchantRole() {
6972 if($this->apiSessionObject->getRoleType() == Gpf_Api_Session::AFFILIATE) {
6973 throw new Gpf_Exception('Only merchant is allowed to pay affiliates.');
6974 }
6975 }
6976 }
6977
6978} //end Pap_Api_PayoutsGrid
6979
6980if (!class_exists('Pap_Api_PayoutsHistoryGrid', false)) {
6981 class Pap_Api_PayoutsHistoryGrid extends Gpf_Rpc_GridRequest {
6982 public function __construct(Gpf_Api_Session $session) {
6983 if($session->getRoleType() == Gpf_Api_Session::AFFILIATE) {
6984 throw new Gpf_Exception('Only merchant can view payouts history. Please login as merchant.');
6985 }
6986 parent::__construct('Pap_Merchants_Payout_PayoutsHistoryGrid', 'getRows', $session);
6987 }
6988
6989 public function getPayeesDeatilsInfo($payoutId) {
6990 $this->checkMerchantRole();
6991 $request = new Gpf_Rpc_DataRequest('Pap_Merchants_Payout_PayoutsHistoryGrid', 'payeesDetails', $this->apiSessionObject);
6992 $request->addFilter('id', 'E', $payoutId);
6993 $request->sendNow();
6994 $results = $request->getData();
6995
6996 $output = array();
6997
6998 for ($i=0; $i<$results->getSize(); $i++) {
6999 $userinfo = $results->getValue('user' . $i);
7000 $data = new Gpf_Rpc_Data();
7001 $data->loadFromObject($userinfo);
7002 $output[] = $data;
7003 }
7004 return $output;
7005 }
7006
7007 private function checkMerchantRole() {
7008 if($this->apiSessionObject->getRoleType() == Gpf_Api_Session::AFFILIATE) {
7009 throw new Gpf_Exception('Only merchant is allowed to to view payee details.');
7010 }
7011 return true;
7012 }
7013 }
7014
7015} //end Pap_Api_PayoutsHistoryGrid
7016
7017if (!class_exists('Pap_Api_Session', false)) {
7018 class Pap_Api_Session extends Gpf_Api_Session {
7019
7020 const AUTHENTICATE_CLASS_NAME = 'Pap_Api_AuthService';
7021
7022
7023 protected function getAuthenticateClassName() {
7024 return self::AUTHENTICATE_CLASS_NAME;
7025 }
7026 }
7027
7028} //end Pap_Api_Session
7029
7030if (!class_exists('Gpf_Net_Http_Client', false)) {
7031 class Gpf_Net_Http_Client extends Gpf_Net_Http_ClientBase {
7032
7033 protected function isNetworkingEnabled() {
7034 return true;
7035 }
7036
7037 protected function setProxyServer(Gpf_Net_Http_Request $request) {
7038 if (defined('PAP_API_PROXY_SERVER')) {
7039 $proxyServer = PAP_API_PROXY_SERVER;
7040
7041 if (defined('PAP_API_PROXY_PORT')) {
7042 $proxyPort = PAP_API_PROXY_PORT;
7043 } else {
7044 $proxyPort = '';
7045 }
7046 if (defined('PAP_API_PROXY_USER')) {
7047 $proxyUser = PAP_API_PROXY_USER;
7048 } else {
7049 $proxyUser = '';
7050 }
7051 if (defined('PAP_API_PROXY_PASSWORD')) {
7052 $proxyPassword = PAP_API_PROXY_PASSWORD;
7053 } else {
7054 $proxyPassword = '';
7055 }
7056 $request->setProxyServer($proxyServer, $proxyPort, $proxyUser, $proxyPassword);
7057 }
7058 }
7059 }
7060}
7061
7062?>
7063