all new 51/28951/2
authormblunck <michael.blunck@phth.de>
Sat, 29 Mar 2014 17:35:44 +0000 (18:35 +0100)
committerMichael Blunck <michael.blunck@phth.de>
Sat, 29 Mar 2014 18:58:16 +0000 (19:58 +0100)
Change-Id: I5e59f1f2024b5bf2381b1d7b5bcc88f130a0489a
Reviewed-on: https://review.typo3.org/28949
Reviewed-by: Michael Blunck
Tested-by: Michael Blunck
(cherry picked from commit debfbd54c5e6f80fb33ac2e01bc531d2df21f432)
Reviewed-on: https://review.typo3.org/28951

80 files changed:
Classes/Controller/PingbackController.php [new file with mode: 0644]
Classes/Domain/Model/Pingback.php [new file with mode: 0644]
Classes/Domain/Repository/PingbackRepository.php [new file with mode: 0644]
Classes/Domain/Validator/PingbackValidator.php [new file with mode: 0644]
Classes/Hook/Tcemain.php [new file with mode: 0644]
Classes/Library/fXmlRpc/AbstractDecorator.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Client.php [new file with mode: 0644]
Classes/Library/fXmlRpc/ClientInterface.php [new file with mode: 0644]
Classes/Library/fXmlRpc/CodeGenerator/XmlReaderParserBitmaskGenerator.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Exception/ExceptionInterface.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Exception/HttpException.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Exception/InvalidArgumentException.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Exception/MissingExtensionException.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Exception/ResponseException.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Exception/RuntimeException.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Exception/SerializationException.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Exception/TcpException.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Exception/TransportException.php [new file with mode: 0644]
Classes/Library/fXmlRpc/ExtensionSupportInterface.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Multicall.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Parser/NativeParser.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Parser/ParserInterface.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Parser/XmlReaderParser.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Proxy.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Serializer/NativeSerializer.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Serializer/SerializerInterface.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Serializer/XmlWriterSerializer.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Timing/AbstractTimerBridge.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Timing/MonologTimerBridge.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Timing/Psr3TimerBridge.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Timing/TimerInterface.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Timing/TimingDecorator.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Timing/ZendFrameworkOneTimerBridge.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Timing/ZendFrameworkTwoTimerBridge.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Transport/BuzzBrowserBridge.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Transport/CurlTransport.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Transport/GuzzleBridge.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Transport/PeclHttpBridge.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Transport/StreamSocketTransport.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Transport/TransportInterface.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Transport/ZendFrameworkOneHttpClientBridge.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Transport/ZendFrameworkTwoHttpClientBridge.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Value/Base64.php [new file with mode: 0644]
Classes/Library/fXmlRpc/Value/Base64Interface.php [new file with mode: 0644]
Classes/Service/PingbackClient.php [new file with mode: 0644]
Configuration/ExtensionBuilder/settings.yaml [new file with mode: 0644]
Configuration/TCA/Pingback.php [new file with mode: 0644]
Configuration/TypoScript/base.setup.ts [new file with mode: 0644]
Configuration/TypoScript/constants.txt [new file with mode: 0644]
Configuration/TypoScript/setup.txt [new file with mode: 0644]
ExtensionBuilder.json [new file with mode: 0644]
Readme.rst [new file with mode: 0644]
Resources/Private/.htaccess [new file with mode: 0644]
Resources/Private/Backend/Layouts/Default.html [new file with mode: 0644]
Resources/Private/Backend/Partials/Pingback/Properties.html [new file with mode: 0644]
Resources/Private/Backend/Templates/Pingback/Administer.html [new file with mode: 0644]
Resources/Private/Backend/Templates/Pingback/Show.html [new file with mode: 0644]
Resources/Private/Language/de_locallang.xlf [new file with mode: 0644]
Resources/Private/Language/locallang.xlf [new file with mode: 0644]
Resources/Private/Language/locallang_csh_tx_pongback_domain_model_pingback.xlf [new file with mode: 0644]
Resources/Private/Language/locallang_db.xlf [new file with mode: 0644]
Resources/Private/Language/locallang_pongbackbackend.xlf [new file with mode: 0644]
Resources/Private/Layouts/Default.html [new file with mode: 0644]
Resources/Private/Partials/Pingback/Properties.html [new file with mode: 0644]
Resources/Private/Templates/Pingback/List.html [new file with mode: 0644]
Resources/Private/Templates/Pingback/Show.html [new file with mode: 0644]
Resources/Public/Icons/relation.gif [new file with mode: 0644]
Resources/Public/Icons/tx_pongback_domain_model_pingback.gif [new file with mode: 0644]
Resources/Public/Styles/PongbackStyle.css [new file with mode: 0644]
Tests/Unit/Controller/PingbackControllerTest.php [new file with mode: 0644]
Tests/Unit/Domain/Model/PingbackTest.php [new file with mode: 0644]
doc/Benutzerhandbuch.sxw [new file with mode: 0644]
doc/manual.sxw [new file with mode: 0644]
ext_autoload.php [new file with mode: 0644]
ext_conf_template.txt [new file with mode: 0644]
ext_emconf.php [new file with mode: 0644]
ext_icon.gif [new file with mode: 0644]
ext_localconf.php [new file with mode: 0644]
ext_tables.php [new file with mode: 0644]
ext_tables.sql [new file with mode: 0644]

diff --git a/Classes/Controller/PingbackController.php b/Classes/Controller/PingbackController.php
new file mode 100644 (file)
index 0000000..cf5fcc3
--- /dev/null
@@ -0,0 +1,236 @@
+<?php
+
+namespace PHTH\Pongback\Controller;
+
+/* * *************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2014 Michael Blunck <michael.blunck@phth.de>, PHTH
+ *  
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ * ************************************************************* */
+
+/**
+ *
+ *
+ * @package pongback
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
+ *
+ */
+class PingbackController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
+
+    
+    /**
+     * pingbackRepository
+     *
+     * @var \PHTH\Pongback\Domain\Repository\PingbackRepository
+     * @inject
+     */
+    protected $pingbackRepository;
+
+    /* Deaktiviert FlashMessage 
+    * @see Tx_Extbase_MVC_Controller_ActionController::getErrorFlashMessage()
+    */
+    protected function getErrorFlashMessage() {
+        return FALSE;
+    }
+
+    /**
+     * action list
+     *
+     * @return void
+     */
+    public function administerAction() {
+       
+        $pingbacks = $this->pingbackRepository->findByDeleted('0');
+        
+        $this->view->assign('pingbacks', $pingbacks);
+        
+        
+    }
+      /**
+     * action list
+     *
+     * @return void
+     */
+    public function listAction() {
+       
+        $pingbacks = $this->pingbackRepository->findVisible();
+                
+        $this->view->assign('pingbacks', $pingbacks);
+        
+        
+    }
+    
+    
+
+    /**
+     * action show
+     *
+     * @param \PHTH\Pongback\Domain\Model\Pingback $pingback
+     * @return void
+     */
+    public function showAction(\PHTH\Pongback\Domain\Model\Pingback $pingback) {
+          
+        $this->view->assign('pingback', $pingback);
+       
+         $this->getErrorFlashMessage(); 
+       
+    }
+      /**
+     * action publish
+     *
+     * @param string $pingback
+     * @return void
+     */
+    public function unpublishAction($pingback) {
+       $pingback = $this->pingbackRepository->findByUid((int)$pingback);
+        $pingback->setHidden(1); 
+        $this->pingbackRepository->update($pingback); 
+       $this->redirect('administer'); 
+    } 
+    
+         /**
+     * action unpublish
+     *
+     * @param string $pingback
+     * @return void
+     */
+    public function publishAction($pingback) {
+        $pingback = $this->pingbackRepository->findByUid((int)$pingback);
+        $pingback->setHidden(0); 
+        $this->pingbackRepository->update($pingback); 
+        $this->redirect('administer'); 
+    } 
+    
+    
+    /**
+     * action delete
+     *
+     * @param string $pingback
+     * @return void
+     */
+    public function deleteAction($pingback) {
+        $pingback = $this->pingbackRepository->findByUid((int)$pingback);
+        $this->pingbackRepository->remove($pingback); 
+        //$this->persistenceManager->persist();
+        
+        $this->redirect('administer'); 
+    }
+    /**
+     * edit delete
+     *
+     * @param \PHTH\Pongback\Domain\Model\Pingback $pingback
+     * @return void
+     */
+    public function editAction(\PHTH\Pongback\Domain\Model\Pingback $pingback) {
+        $this->view->assign('pingback', $pingback);
+    }
+    
+    /**
+     * server
+     *
+     * @return string $response
+     */
+    public function serverAction() {
+
+       
+        $fp = fopen('php://input', 'rb');
+        stream_filter_append($fp, 'dechunk', STREAM_FILTER_READ);
+        $HTTP_RAW_POST_DATA = stream_get_contents($fp);
+
+        $xmlrpcServerHandler = xmlrpc_server_create();
+        xmlrpc_server_register_method($xmlrpcServerHandler, "pingback.ping", array($this, "pingback"));
+        $response = xmlrpc_server_call_method($xmlrpcServerHandler, $HTTP_RAW_POST_DATA, null);
+        return $response;
+    }
+    /**
+     * 
+     * @param string $method_name
+     * @param array $xmlRpcParams
+     * @param type $app_data
+     */
+    public function pingback($method_name, $xmlRpcParams, $app_data) {
+        
+        
+        /**
+         * We must implement some Hooks to validate some important content, the URL, the content from other page an  send an email to the owner of the blog
+         */
+        $pingback = $this->objectManager->get('PHTH\Pongback\Domain\Model\Pingback');
+       
+            if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['pongback']['validatePingback'])) {
+                foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['pongback']['validatePingback'] as $userFunc) {
+                    if (count($pingback->getValidationErrors()) < 1) {
+                        $params = array(
+                            'pingback' => $pingback,
+                            'params' => $xmlRpcParams
+                        );
+                       
+                        \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($userFunc, $params, $this);
+                    } else {
+                        break;
+                    }
+                }
+            }
+                                 
+        if(count($pingback->getValidationErrors()) > 0) {
+                $errors = $pingback->getValidationErrors();
+                
+                return $errors[0]; 
+            } else {
+                /**
+                 * saved the incoming Pongback to the Database 
+                 */
+                $pongbackConf = (array)@unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['pongback']);
+                if (!$pongbackConf['enableAutoPublishing']) {
+                    $pingback->setHidden(1);
+                }
+                $this->pingbackRepository->add($pingback);
+               
+                return \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("xmlrpc.pingback.ping.success", 'pongback');      
+            } 
+            
+            
+    }
+    
+   /**
+    * Generates an XML formatted Fault Code
+    * 
+    * @param string $errno
+    * @param string $errstr
+    * @param string $errfile
+    * @param string $errline
+    * @param string $errcontext
+    */
+   public function return_xmlrpc_error($errno, $errstr, $errfile=NULL, $errline=NULL, $errcontext=NULL){
+       
+       header("Content-type: text/xml; charset=UTF-8"); 
+       print(xmlrpc_encode_request(NULL, array(
+             'faultCode'=>$errno
+               ,'faultString'=>"Remote XMLRPC Error from ".$_SERVER['SERVER_NAME'].": $errstr in $errfile:$errline"
+       ))); 
+       die(); 
+   }  
+  // set_error_handler('return_xmlrpc_error'); 
+    
+  
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Domain/Model/Pingback.php b/Classes/Domain/Model/Pingback.php
new file mode 100644 (file)
index 0000000..8051679
--- /dev/null
@@ -0,0 +1,252 @@
+<?php
+namespace PHTH\Pongback\Domain\Model;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2014 Michael Blunck <michael.blunck@phth.de>, PHTH
+ *  
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ *
+ *
+ * @package pongback
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, 
+ * version 3 or later
+ *
+ */
+
+class Pingback extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+    /**
+     * sourceLink
+     *
+     * @var \string
+     * @validate NotEmpty
+     */
+    protected $sourceLink;
+
+    /**
+     * pingClient
+     *
+     * @var \string
+     */
+    protected $pingClient;
+
+    /**
+     * pingRessource
+     *
+     * @var \string
+     */
+    protected $pingRessource;
+
+    /**
+     * targetLink
+     *
+     * @var \string
+     * @validate NotEmpty
+     */
+    protected $targetLink;
+
+    /**
+     * serializedInformation
+     *
+     * @var \string
+     * @validate NotEmpty
+     */
+    protected $serializedInformation;
+
+    /**
+     * validation error
+     *
+     * @var \array
+     * 
+     */
+    protected $validationError;
+
+    /**
+     * Returns the sourceLink
+     *
+     * @return \string $sourceLink
+     */
+    public function getSourceLink() {
+        
+        return $this->sourceLink;
+    }
+
+    /**
+     * Sets the sourceLink
+     *
+     * @param \string $sourceLink
+     * @return void
+     */
+    public function setSourceLink($sourceLink) {
+       
+        $this->sourceLink = $sourceLink;
+    }
+
+    /**
+     * @var boolean
+     */
+    protected $hidden;
+
+    /**
+     * @return boolean $hidden
+     */
+    public function getHidden() {
+        return $this->hidden;
+    }
+
+    /**
+     * @return boolean $hidden
+     */
+    public function isHidden() {
+        return $this->getHidden();
+    }
+
+    /**
+     * @param boolean $hidden
+     * @return void
+     */
+    public function setHidden($hidden) {
+        $this->hidden = $hidden;
+    }
+
+       /**
+     * Returns the pingClient
+     *
+     * @return \string $pingClient
+     */
+    public function getPingClient() {
+        return $this->pingClient;
+    }
+
+    /**
+     * Sets the pingClient
+     *
+     * @param \string $pingClient
+     * @return void
+     */
+    public function setPingClient($pingClient) {
+        $this->pingClient = $pingClient;
+    }
+
+    /**
+     * Returns the pingRessource
+     *
+     * @return \string $pingRessource
+     */
+    public function getPingRessource() {
+        return $this->pingRessource;
+    }
+
+    /**
+     * Sets the pingRessource
+     *
+     * @param \string $pingRessource
+     * @return void
+     */
+    public function setPingRessource($pingRessource) {
+        $this->pingRessource = $pingRessource;
+    }
+
+    /**
+     * Adds the validationError
+     *
+     * @return \string $validationError
+     */
+    public function addValidationError($validationError) {
+        $this->validationErrors[] = $validationError;
+    }
+
+    /**
+     * Sets the validationErrors
+     *
+     * @return \array $validationErrors
+     */
+    public function setValidationErrors($validationErrors) {
+        $this->validationErrors = $validationErrors;
+    }
+
+    /**
+     * Returns the validationErrors
+     *
+     * @return \array $validationErrors
+     */
+    public function getValidationErrors() {
+        return $this->validationErrors;
+    }
+
+    /**
+     * Returns the targetLink
+     *
+     * @return \string $targetLink
+     */
+    public function getTargetLink() {
+        return $this->targetLink;
+    }
+
+    /**
+     * Sets the targetLink
+     *
+     * @param \string $targetLink
+     * @return void
+     */
+    public function setTargetLink($targetLink) {
+        $this->targetLink = $targetLink;
+    }
+
+    /**
+     * Returns the serializedInformation
+     *
+     * @return \string $serializedInformation
+     */
+    public function getSerializedInformation() {
+
+        return $this->serializedInformation;
+    }
+
+    /**
+     * Sets the serializedInformation
+     *
+     * @param \string $serializedInformation
+     * @return void
+     */
+    public function setSerializedInformation($serializedInformation) {
+
+        $this->serializedInformation = $serializedInformation;
+                
+            
+    }
+
+
+    /**
+     * information changed in object
+     * @param type $param
+     */
+    public function seralizeInformation($param) {
+
+        $this->setSerializedInformation(serialize($param));
+    }
+    
+}
+            
+?>
\ No newline at end of file
diff --git a/Classes/Domain/Repository/PingbackRepository.php b/Classes/Domain/Repository/PingbackRepository.php
new file mode 100644 (file)
index 0000000..3f79dcb
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+namespace PHTH\Pongback\Domain\Repository;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2014 Michael Blunck <michael.blunck@phth.de>, PHTH
+ *  
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ *
+ *
+ * @package pongback
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
+ *
+ */
+class PingbackRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
+
+    public function initializeObject() {
+        /** @var $querySettings \TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings */
+        $querySettings = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Typo3QuerySettings');
+        // go for $defaultQuerySettings = $this->createQuery()->getQuerySettings(); if you want to make use of the TS persistence.storagePid with defaultQuerySettings(), see #51529 for details
+        // don't add the pid constraint
+        $querySettings->setRespectStoragePage(FALSE);
+        // set the storagePids to respect
+        //$querySettings->setStoragePageIds(array(1, 26, 989));
+        // don't add fields from enablecolumns constraint
+        // this function is deprecated!
+        $querySettings->setRespectEnableFields(FALSE);
+
+        // define the enablecolumn fields to be ignored
+        // if nothing else is given, all enableFields are ignored
+        //$querySettings->setIgnoreEnableFields(TRUE);       
+        // define single fields to be ignored
+        //$querySettings->setEnableFieldsToBeIgnored(array('disabled','starttime'));
+        // add deleted rows to the result
+        //$querySettings->setIncludeDeleted(TRUE);
+        // don't add sys_language_uid constraint
+        //$querySettings->setRespectSysLanguage(FALSE);
+        // perform translation to dedicated language
+        //$querySettings->setSysLanguageUid(42);
+        $this->setDefaultQuerySettings($querySettings);
+        
+        
+    }
+    public function findVisible() {
+        
+        $query = $this->createQuery();
+        
+        // SELECT * FROM tx_ _ _ pingback WHERE ( deleted = 0 AND hidden = 0 ) ORDER BY crdate DESC;
+        $query = $query->matching(
+            $query->logicalAnd(
+                $query->equals('deleted', '0'),
+                $query->equals('hidden', '0')
+            )
+        )
+        ->setOrderings(
+            array('crdate' =>\TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING)
+        );
+
+        return $query->execute();
+        
+    }
+
+}
+?>
\ No newline at end of file
diff --git a/Classes/Domain/Validator/PingbackValidator.php b/Classes/Domain/Validator/PingbackValidator.php
new file mode 100644 (file)
index 0000000..78a0a83
--- /dev/null
@@ -0,0 +1,118 @@
+<?php
+namespace PHTH\Pongback\Domain\Validator;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2014 Michael Blunck <michael.blunck@phth.de>, PHTH
+ *  
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ *
+ *
+ * @package pongback
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
+ *
+ */
+class PingbackValidator {
+
+    
+    
+
+
+    public function validateTargetUri(&$params) {
+        $pingback = $params['pingback'];
+        $targetLink = $params['params'][0];
+        $sourceLink = $params['params'][1];
+        $matchLink = $_SERVER['SERVER_NAME'];
+        
+        if (strpos($targetLink, $matchLink) > 0) {
+            $pingback->setSourceLink($sourceLink);
+            $pingback->setTargetLink($targetLink);
+            
+        } else {
+            $error = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('PHTH\Pongback\Controller\PingbackController');
+            
+            //$pingback->addValidationError(\TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tx_pongback_domain_model_pingback.error_targetlink", 'pongback'));
+            
+            $pingback->addValidationError($error->return_xmlrpc_error('32', \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tx_pongback_domain_model_pingback.error_targetlink"), 'pongback'));
+            
+        }
+    }
+
+    public function getInformationFromOtherWebsite(&$params) {
+
+        $pingback = $params['pingback'];
+        $targetLink = $params['params'][0];
+        $sourceLink = $params['params'][1];
+       
+        /**
+         * 
+         * Pingback add to the Timestamp because its need an unique identifier
+         */
+        $pseudotag = '#%$PINGBACK-' . time() . '$%#';
+        $sourceContent = file_get_contents($sourceLink);
+        $sourceContent = preg_replace('@<a [^>]*href="' . preg_quote($targetLink) . '"[^>]*>@', $pseudotag, $sourceContent,100,$count);
+        /**
+         * 
+         * @todo other inputfile 
+         * 
+         */
+        
+        file_put_contents('sample.php', $sourceContent);
+        $treffer = "";
+        $tagLessData = '';
+
+        $handle = @fopen("sample.php", "r");
+        if ($handle) {
+            while (!feof($handle)) {
+                $tagLessData .= fgetss($handle, 4096);
+            }
+            fclose($handle);
+        }
+
+        /**
+         * Replace the '#%$PINGBACK- with an empty String, because we dont want it in the Output 
+         */
+        $tagLessData = preg_replace('/\s+/', ' ', $tagLessData);
+        $pos = strpos($tagLessData, $pseudotag);
+
+       if ($pos !== FALSE) {
+
+            $informationString = str_replace($pseudotag, '', $tagLessData);
+
+            $informationString = '...' . trim(substr($informationString, $pos - 100, 200)) . '...';
+
+            $pingback->setSerializedInformation($informationString);
+           
+        } else {
+            
+            
+            $error = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('PHTH\Pongback\Controller\PingbackController');
+                                
+            $pingback->addValidationError($error->return_xmlrpc_error('33', \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tx_pongback_domain_model_pingback.error_noInformations"), 'pongback'));
+        }
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/Classes/Hook/Tcemain.php b/Classes/Hook/Tcemain.php
new file mode 100644 (file)
index 0000000..5ff2735
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+
+namespace PHTH\Pongback\Hook;
+
+class Tcemain {
+
+    public function processDatamap_postProcessFieldArray($status, $table, $id, $fieldArray, $ref) {
+
+        // @todo: make tables configurable
+        /**
+         * To search content after saving about Hyperlinks 
+         */
+        if ($table == 'tt_content' && is_array($fieldArray)) {
+            $links = array();
+
+            foreach ($fieldArray as $field) {
+                preg_match_all("/((http|https):\/\/[^\s]*)/", $field, $matches);
+                foreach ($matches[0] as $match) {
+
+                    $links[$match] = $match;
+                }
+            }
+
+            if (count($links) > 0) {
+
+                /**
+                 * @todo respect the enablefields!
+                 * to provide to set the enablefields  
+                 * Takes the full tt_content-row when is not hidden
+                 * we dont need to send pingbacks for hidden elements 
+                 * 
+                 */
+                $row = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecord($table, $id, '*', ' AND hidden = 0 AND (fe_group = \'\' OR fe_group = 0) ');
+
+                if (is_array($row)) {
+
+                    // @todo respect the enablefields!
+                    /**
+                     * take the page that is not hidden and get the unique pid to set the URL 
+                     */
+                    $page = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecord('pages', $row['pid'], '*', ' AND hidden = 0 AND (fe_group = \'\' OR fe_group = 0) ');
+
+                    if (is_array($page)) {
+
+                         
+                        $permalinkParameters = array();
+                        /**
+                         * We need to instanciate the TSFE(TypoScript Frontend) to build a typolink via a content object($cObj)
+                         * 
+                         */
+                        $this->buildTSFE($ref);
+                        $cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tslib_cObj');
+                        $cObj->start(array(), '');
+
+                        $pingbackClient = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('PHTH\Pongback\Service\PingbackClient');
+                      
+                        /**
+                         * 
+                         */
+                        foreach ($links as $link) {
+                            $typolinkConf = array(
+                                'additionalParams' => $permalinkParameters,
+                                'parameter' => $row['pid'],
+                                'useCacheHash' => true,
+                                'returnLast' => 'url',
+                                'forceAbsoluteUrl' => true
+                            );
+
+                            $permaLink = $cObj->typoLink('', $typolinkConf);
+
+
+                            try {
+                                $response = $pingbackClient->send($link, $permaLink);
+                                $o_flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+                                        '\TYPO3\CMS\Core\Messaging\FlashMessage', 
+                                        \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tcemain.pingback.ping.accepted", 'pongback', array($link)),
+                                        \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tcemain.pingback.ping.accepted_title", 'pongback'), 
+                                        \TYPO3\CMS\Core\Messaging\FlashMessage::OK 
+                                );
+                                \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($o_flashMessage);
+                            } catch (\fXmlRpc\Exception\ResponseException $ex) {
+                                $o_flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+                                        '\TYPO3\CMS\Core\Messaging\FlashMessage', 
+                                        \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tcemain.pingback.ping.refused", 'pongback', array($link,$ex->getFaultString())),
+                                        \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tcemain.pingback.ping.refused_title", 'pongback'), 
+                                        \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING 
+                                );
+                                \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($o_flashMessage);
+                            }
+                        }
+                    } else { 
+                        $o_flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+                                '\TYPO3\CMS\Core\Messaging\FlashMessage', 
+                                \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tcemain.pingback.ping.not_sent", 'pongback'), 
+                                \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tcemain.pingback.ping.not_sent_title", 'pongback'),
+                                \TYPO3\CMS\Core\Messaging\FlashMessage::NOTICE
+                        );
+                        \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($o_flashMessage);
+                    }
+                }
+            }
+        }
+    }
+/** 
+ * 
+ * @param type $ref
+ */
+    
+    public function buildTSFE($ref) {
+        $TSFEclassName = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tslib_fe');
+
+        if (!is_object($GLOBALS['TT'])) {
+            $GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\TimeTracker;
+            $GLOBALS['TT']->start();
+        }
+
+        // Create the TSFE class.
+        $GLOBALS['TSFE'] = new $TSFEclassName($GLOBALS['TYPO3_CONF_VARS'], $ref->pid, '0', 1, '', '', '', '');
+        $GLOBALS['TSFE']->initFEuser();
+        $GLOBALS['TSFE']->fetch_the_id();
+        $GLOBALS['TSFE']->getPageAndRootline();
+        $GLOBALS['TSFE']->initTemplate();
+        $GLOBALS['TSFE']->tmpl->getFileName_backPath = PATH_site;
+        $GLOBALS['TSFE']->forceTemplateParsing = 1;
+        $GLOBALS['TSFE']->getConfigArray();
+    } 
+    
+}
+
+?>
diff --git a/Classes/Library/fXmlRpc/AbstractDecorator.php b/Classes/Library/fXmlRpc/AbstractDecorator.php
new file mode 100644 (file)
index 0000000..74634c6
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc;
+
+/**
+ * Abstract base class for client decorators
+ *
+ * Extend this base class if you want to decorate functionality of the client
+ */
+abstract class AbstractDecorator implements ClientInterface
+{
+    /**
+     * @var ClientInterface
+     */
+    protected $wrapped;
+
+    /**
+     * {@inheritdoc}
+     */
+    public function __construct(ClientInterface $wrapped)
+    {
+        $this->wrapped = $wrapped;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setUri($uri)
+    {
+        return $this->wrapped->setUri($uri);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getUri()
+    {
+        return $this->wrapped->getUri();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function prependParams(array $params)
+    {
+        return $this->wrapped->prependParams($params);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPrependParams()
+    {
+        return $this->wrapped->getPrependParams();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function appendParams(array $params)
+    {
+        return $this->wrapped->appendParams($params);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getAppendParams()
+    {
+        return $this->wrapped->getAppendParams();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function call($methodName, array $arguments = [])
+    {
+        return $this->wrapped->call($methodName, $arguments);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function multicall()
+    {
+        return $this->wrapped->multicall();
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Client.php b/Classes/Library/fXmlRpc/Client.php
new file mode 100644 (file)
index 0000000..7ada398
--- /dev/null
@@ -0,0 +1,174 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc;
+
+use fXmlRpc\Transport\TransportInterface;
+use fXmlRpc\Transport\StreamSocketTransport;
+use fXmlRpc\Parser\ParserInterface;
+use fXmlRpc\Parser\XmlReaderParser;
+use fXmlRpc\Serializer\SerializerInterface;
+use fXmlRpc\Serializer\XmlWriterSerializer;
+use fXmlRpc\Exception\ResponseException;
+use fXmlRpc\Exception\InvalidArgumentException;
+
+final class Client implements ClientInterface
+{
+    /**
+     * @var string
+     */
+    private $uri;
+
+    /**
+     * @var Transport\TransportInterface
+     */
+    private $transport;
+
+    /**
+     * @var Parser\ParserInterface
+     */
+    private $parser;
+
+    /**
+     * @var Serializer\SerializerInterface
+     */
+    private $serializer;
+
+    /**
+     * @var array
+     */
+    private $prependParams = [];
+
+    /**
+     * @var array
+     */
+    private $appendParams = [];
+
+    /**
+     * Create new client instance
+     *
+     * If no specific transport, parser or serializer is passed, default implementations
+     * are used.
+     *
+     * @param string                         $uri
+     * @param Transport\TransportInterface   $transport
+     * @param Parser\ParserInterface         $parser
+     * @param Serializer\SerializerInterface $serializer
+     */
+    public function __construct(
+        $uri = null,
+        TransportInterface $transport = null,
+        ParserInterface $parser = null,
+        SerializerInterface $serializer = null
+    )
+    {
+        $this->uri = $uri;
+        $this->transport = $transport ?: new StreamSocketTransport();
+        $this->parser = $parser ?: new XmlReaderParser();
+        $this->serializer = $serializer ?: new XmlWriterSerializer();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setUri($uri)
+    {
+        if (!is_string($uri)) {
+            throw InvalidArgumentException::expectedParameter(0, 'string', $uri);
+        }
+
+        $this->uri = $uri;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getUri()
+    {
+        return $this->uri;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function prependParams(array $params)
+    {
+        $this->prependParams = $params;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getPrependParams()
+    {
+        return $this->prependParams;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function appendParams(array $params)
+    {
+        $this->appendParams = $params;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getAppendParams()
+    {
+        return $this->appendParams;
+    }
+
+    /**
+     * {@inheritdoc}
+     * @throws Exception\ResponseException
+     */
+    public function call($methodName, array $params = [])
+    {
+        if (!is_string($methodName)) {
+            throw InvalidArgumentException::expectedParameter(0, 'string', $methodName);
+        }
+
+        $params = array_merge($this->prependParams, $params, $this->appendParams);
+
+        $response = $this->parser->parse(
+            $this->transport->send($this->uri, $this->serializer->serialize($methodName, $params)),
+            $isFault
+        );
+
+        if ($isFault) {
+            throw ResponseException::fault($response);
+        }
+
+        return $response;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function multicall()
+    {
+        return new Multicall($this);
+    }
+}
diff --git a/Classes/Library/fXmlRpc/ClientInterface.php b/Classes/Library/fXmlRpc/ClientInterface.php
new file mode 100644 (file)
index 0000000..eff0df6
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc;
+
+interface ClientInterface
+{
+    /**
+     * Set endpoint URI
+     *
+     * @param string $uri
+     * @return null
+     */
+    public function setUri($uri);
+
+    /**
+     * Return endpoint URI
+     *
+     * @return string
+     */
+    public function getUri();
+
+    /**
+     * Set default params to be prepended for each call (e.g. authorization information)
+     *
+     * @param array $params
+     * @return null
+     */
+    public function prependParams(array $params);
+
+    /**
+     * @return array
+     */
+    public function getPrependParams();
+
+    /**
+     * Set default params to be appended for each call (e.g. authorization information)
+     *
+     * @param array $params
+     * @return null
+     */
+    public function appendParams(array $params);
+
+    /**
+     * @return array
+     */
+    public function getAppendParams();
+
+    /**
+     * Execute remote call
+     *
+     * @param string $methodName
+     * @param array  $params
+     * @return mixed
+     */
+    public function call($methodName, array $params = []);
+
+    /**
+     * Start sequence of multiccallss
+     *
+     * @return Multicall
+     */
+    public function multicall();
+}
diff --git a/Classes/Library/fXmlRpc/CodeGenerator/XmlReaderParserBitmaskGenerator.php b/Classes/Library/fXmlRpc/CodeGenerator/XmlReaderParserBitmaskGenerator.php
new file mode 100644 (file)
index 0000000..9e05ce5
--- /dev/null
@@ -0,0 +1,155 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+namespace fXmlRpc\CodeGenerator;
+
+class XmlReaderParserBitmaskGenerator
+{
+    private $basicTypes = [
+        'methodResponse',
+        'params',
+        'fault',
+        'param',
+        'value',
+        'array',
+        'member',
+        'name',
+        '#text',
+        'string',
+        'struct',
+        'int',
+        'biginteger',
+        'i8',
+        'i4',
+        'i2',
+        'i1',
+        'boolean',
+        'double',
+        'float',
+        'bigdecimal',
+        'dateTime.iso8601',
+        'dateTime',
+        'base64',
+        'nil',
+        'dom',
+        'data',
+    ];
+
+    private $combinedTypes = [];
+
+    private $typeCount = 0;
+
+    private $values = [];
+
+    public function __construct()
+    {
+        $this->combinedTypes = [
+            'expectedForMethodResponse' => ['params', 'fault'],
+            'expectedForMember' => ['name', 'value'],
+            'expectedForSimpleType' => ['#text', 'value'],
+            'expectedForNil' => ['nil', 'value'],
+            'expectedForValue' => [
+                'string',
+                'array',
+                'struct',
+                'int',
+                'biginteger',
+                'i8',
+                'i4',
+                'i2',
+                'i1',
+                'boolean',
+                'double',
+                'float',
+                'bigdecimal',
+                'dateTime.iso8601',
+                'dateTime',
+                'base64',
+                'nil',
+                'dom',
+                '#text'
+            ],
+            'expectedForStruct' => ['member', 'struct', 'value'],
+            'expectedForData' => ['data', 'value', 'array'],
+            'expectedAfterValue' => [
+                'param',
+                'value',
+                'data',
+                'member',
+                'name',
+                'int',
+                'i4',
+                'i2',
+                'i1',
+                'base64',
+                'fault'
+            ],
+            'expectedAfterParam' => ['param', 'params'],
+            'expectedAfterName' => ['value', 'member'],
+            'expectedAfterMember' => ['struct', 'member'],
+            'allFlags' => $this->basicTypes,
+        ];
+
+        $this->typeCount = count($this->basicTypes);
+    }
+
+    private function createBitmaskVariable($type, $bitmask, $prefix = '')
+    {
+        $variableName = preg_match('/^\w+[\d\w_]*$/', $type)
+            ? 'static $' . $prefix . $type
+            : '${\'' . $prefix . $type . '\'}';
+        $this->values[$type] = $bitmask;
+
+        return $variableName . ' = 0b' . sprintf('%0' . $this->typeCount . 'b', $this->values[$type]) . ';';
+    }
+
+    public function generate()
+    {
+        $code = [];
+        $bitmask = 0b1;
+        foreach ($this->basicTypes as $type) {
+            $code[] = $this->createBitmaskVariable($type, $bitmask, 'flag');
+            $bitmask = $bitmask << 0b01;
+        }
+
+        foreach ($this->combinedTypes as $type => $combination) {
+            $value = 0;
+            foreach ($combination as $subType) {
+                $value |= $this->values[$subType];
+            }
+            $code[] = $this->createBitmaskVariable($type, $value);
+        }
+
+        $commentStart = <<<'EOS'
+// This following assignments are auto-generated using %s
+// Don’t edit manually
+EOS;
+
+        $commentStart = sprintf($commentStart, __CLASS__);
+
+        $commentEnd = '// End of auto-generated code';
+
+        return $commentStart . "\n" . implode("\n", $code) . "\n" . $commentEnd;
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Exception/ExceptionInterface.php b/Classes/Library/fXmlRpc/Exception/ExceptionInterface.php
new file mode 100644 (file)
index 0000000..b61d031
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Exception;
+
+interface ExceptionInterface
+{
+}
diff --git a/Classes/Library/fXmlRpc/Exception/HttpException.php b/Classes/Library/fXmlRpc/Exception/HttpException.php
new file mode 100644 (file)
index 0000000..e4708e8
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Exception;
+
+use Exception;
+
+class HttpException extends TransportException
+{
+    public static function httpError($message, $statusCode, Exception $previous = null)
+    {
+        return new static('An HTTP error occurred: ' . $message, $statusCode, $previous);
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Exception/InvalidArgumentException.php b/Classes/Library/fXmlRpc/Exception/InvalidArgumentException.php
new file mode 100644 (file)
index 0000000..fca19a3
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Exception;
+
+use InvalidArgumentException as BaseInvalidArgumentException;
+
+class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface
+{
+    public static function expectedParameter($position, $expected, $actualValue)
+    {
+        return new static(
+            sprintf(
+                'Expected parameter %d to be of type "%s", "%s" given',
+                $position,
+                $expected,
+                is_object($actualValue)
+                    ? sprintf('%s" of type "%s', gettype($actualValue), get_class($actualValue))
+                    : gettype($actualValue)
+            )
+        );
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Exception/MissingExtensionException.php b/Classes/Library/fXmlRpc/Exception/MissingExtensionException.php
new file mode 100644 (file)
index 0000000..46011aa
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Exception;
+
+class MissingExtensionException extends RuntimeException
+{
+    public static function extensionMissing($extension)
+    {
+        return new static(
+            sprintf('PHP extension "ext/%s" is required but not installed', $extension)
+        );
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Exception/ResponseException.php b/Classes/Library/fXmlRpc/Exception/ResponseException.php
new file mode 100644 (file)
index 0000000..eae816a
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Exception;
+
+class ResponseException extends RuntimeException
+{
+    private $faultCode;
+
+    public static function fault($response)
+    {
+        $exception = new static(isset($response['faultString']) ? $response['faultString'] : 'Unknown');
+        $exception->faultCode = isset($response['faultCode']) ? $response['faultCode'] : 0;
+
+        return $exception;
+    }
+
+    public function getFaultString()
+    {
+        return $this->getMessage();
+    }
+
+    public function getFaultCode()
+    {
+        return $this->faultCode;
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Exception/RuntimeException.php b/Classes/Library/fXmlRpc/Exception/RuntimeException.php
new file mode 100644 (file)
index 0000000..094238e
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Exception;
+
+use RuntimeException as BaseRuntimeException;
+
+class RuntimeException extends BaseRuntimeException implements ExceptionInterface
+{
+    public static function unexpectedTag($tagName, $elements, array $definedVariables, $depth, $xml)
+    {
+        $expectedElements = [];
+        foreach ($definedVariables as $variableName => $variable) {
+            if (substr($variableName, 0, 4) !== 'flag') {
+                continue;
+            }
+
+            if (($elements & $variable) === $variable) {
+                $expectedElements[] = substr($variableName, 4);
+            }
+        }
+
+        return new static(
+            sprintf(
+                'Invalid XML. Expected one of "%s", got "%s" on depth %d (context: "%s")',
+                implode('", "', $expectedElements),
+                $tagName,
+                $depth,
+                $xml
+            )
+        );
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Exception/SerializationException.php b/Classes/Library/fXmlRpc/Exception/SerializationException.php
new file mode 100644 (file)
index 0000000..374e9cc
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Exception;
+
+class SerializationException extends InvalidArgumentException
+{
+    public static function invalidType($value)
+    {
+        return new static(
+            sprintf('Could not serialize %s of type "%s"', gettype($value), get_resource_type($value))
+        );
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Exception/TcpException.php b/Classes/Library/fXmlRpc/Exception/TcpException.php
new file mode 100644 (file)
index 0000000..dad1d7c
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Exception;
+
+use Exception;
+
+class TcpException extends TransportException
+{
+    public static function transportError($error)
+    {
+        $message = $error instanceof Exception ? $error->getMessage() : $error;
+        $previous = $error instanceof Exception ? $error : null;
+
+        return new static('A transport error occurred: ' . $message, null, $previous);
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Exception/TransportException.php b/Classes/Library/fXmlRpc/Exception/TransportException.php
new file mode 100644 (file)
index 0000000..ea2ea34
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Exception;
+
+class TransportException extends RuntimeException
+{
+}
diff --git a/Classes/Library/fXmlRpc/ExtensionSupportInterface.php b/Classes/Library/fXmlRpc/ExtensionSupportInterface.php
new file mode 100644 (file)
index 0000000..8c06a46
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc;
+
+interface ExtensionSupportInterface
+{
+    const EXTENSION_NIL = 'nil';
+
+    /**
+     * Enables extension
+     *
+     * @param  string $extension
+     * @return null
+     */
+    public function enableExtension($extension);
+
+    /**
+     * Disables extension
+     *
+     * @param  string $extension
+     * @return null
+     */
+    public function disableExtension($extension);
+
+    /**
+     * Returns true if an extension is enabled
+     *
+     * @param  string  $extension
+     * @return boolean
+     */
+    public function isExtensionEnabled($extension);
+}
diff --git a/Classes/Library/fXmlRpc/Multicall.php b/Classes/Library/fXmlRpc/Multicall.php
new file mode 100644 (file)
index 0000000..819766a
--- /dev/null
@@ -0,0 +1,181 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc;
+
+use fXmlRpc\Exception\InvalidArgumentException;
+
+final class Multicall
+{
+    /**
+     * @var ClientInterface
+     */
+    private $client;
+
+    /**
+     * @var integer
+     */
+    private $index = 0;
+
+    /**
+     * @var array
+     */
+    private $calls = [];
+
+    /**
+     * @var array
+     */
+    private $handlers = [];
+
+    /**
+     * @var callable
+     */
+    private $onSuccess;
+
+    /**
+     * @var callable
+     */
+    private $onError;
+
+    /**
+     * @param ClientInterface $client
+     */
+    public function __construct(ClientInterface $client)
+    {
+        $this->client = $client;
+    }
+
+    /**
+     * Add a call to the sequence
+     *
+     * @param  string                   $methodName
+     * @param  array                    $params
+     * @param  callable                 $onSuccess
+     * @param  callable                 $onError
+     * @throws InvalidArgumentException
+     * @return self
+     */
+    public function addCall($methodName, array $params = [], $onSuccess = null, $onError = null)
+    {
+        if (!is_string($methodName)) {
+            throw InvalidArgumentException::expectedParameter(1, 'string', $methodName);
+        }
+
+        if ($onSuccess !== null && !is_callable($onSuccess)) {
+            throw InvalidArgumentException::expectedParameter(3, 'callable', $onSuccess);
+        }
+
+        if ($onError !== null && !is_callable($onError)) {
+            throw InvalidArgumentException::expectedParameter(4, 'callable', $onError);
+        }
+
+        $this->calls[$this->index] = compact('methodName', 'params');
+        $this->handlers[$this->index] = compact('onSuccess', 'onError');
+        ++$this->index;
+
+        return $this;
+    }
+
+    /**
+     * @param  callable                 $onSuccess
+     * @throws InvalidArgumentException
+     * @return self
+     */
+    public function onSuccess($onSuccess)
+    {
+        if (!is_callable($onSuccess)) {
+            throw InvalidArgumentException::expectedParameter(1, 'callable', $onSuccess);
+        }
+
+        $this->onSuccess = $onSuccess;
+
+        return $this;
+    }
+
+    /**
+     * @param  callable                 $onError
+     * @throws InvalidArgumentException
+     * @return self
+     */
+    public function onError($onError)
+    {
+        if (!is_callable($onError)) {
+            throw InvalidArgumentException::expectedParameter(1, 'callable', $onError);
+        }
+
+        $this->onError = $onError;
+
+        return $this;
+    }
+
+    /**
+     * Execute multicall request
+     *
+     * @return array
+     */
+    public function execute()
+    {
+        $results = $this->client->call('system.multicall', [$this->calls]);
+
+        foreach ($results as $index => $result) {
+            $this->processResult($this->handlers[$index], $result);
+        }
+
+        return $results;
+    }
+
+    /**
+     * @param array $handler
+     * @param mixed $result
+     */
+    protected function processResult(array $handler, $result)
+    {
+        $isError = is_array($result) && isset($result['faultCode']);
+
+        $this->invokeHandler($handler['onSuccess'], $handler['onError'], $isError, $result);
+        $this->invokeHandler($this->onSuccess, $this->onError, $isError, $result);
+    }
+
+    /**
+     * @param callable|null $onSuccess
+     * @param callable|null $onError
+     * @param boolean       $isError
+     * @param mixed         $result
+     */
+    protected function invokeHandler($onSuccess, $onError, $isError, $result)
+    {
+        if ($isError && $onError !== null) {
+            call_user_func($onError, $result);
+        } elseif ($onSuccess !== null) {
+            call_user_func($onSuccess, $result);
+        }
+    }
+
+    /**
+     * @return ClientInterface
+     */
+    public function getClient()
+    {
+        return $this->client;
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Parser/NativeParser.php b/Classes/Library/fXmlRpc/Parser/NativeParser.php
new file mode 100644 (file)
index 0000000..510f132
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+namespace fXmlRpc\Parser;
+
+use DateTime;
+use DateTimeZone;
+use fXmlRpc\Exception\MissingExtensionException;
+use fXmlRpc\Value\Base64;
+
+class NativeParser implements ParserInterface
+{
+    public function __construct()
+    {
+        if (!extension_loaded('xmlrpc')) {
+            throw MissingExtensionException::extensionMissing('xmlrpc');
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function parse($xmlString, &$isFault)
+    {
+        $result = xmlrpc_decode($xmlString, 'UTF-8');
+
+        $isFault = false;
+
+        $toBeVisited = [&$result];
+        while (isset($toBeVisited[0]) && $value = &$toBeVisited[0]) {
+
+            $type = gettype($value);
+            if ($type === 'object') {
+                $xmlRpcType = $value->{'xmlrpc_type'};
+                if ($xmlRpcType === 'datetime') {
+                    $value = DateTime::createFromFormat(
+                        'Ymd\TH:i:s',
+                        $value->scalar,
+                        isset($timezone) ? $timezone : $timezone = new DateTimeZone('UTC')
+                    );
+
+                } elseif ($xmlRpcType === 'base64') {
+                    if ($value->scalar !== '') {
+                        $value = Base64::serialize($value->scalar);
+                    } else {
+                        $value = null;
+                    }
+                }
+
+            } elseif ($type === 'array') {
+                foreach ($value as &$element) {
+                    $toBeVisited[] = &$element;
+                }
+            }
+
+            array_shift($toBeVisited);
+        }
+
+        if (is_array($result)) {
+            reset($result);
+            $isFault = xmlrpc_is_fault($result);
+        }
+
+        return $result;
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Parser/ParserInterface.php b/Classes/Library/fXmlRpc/Parser/ParserInterface.php
new file mode 100644 (file)
index 0000000..dcf6e52
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Parser;
+
+/**
+ * Parser to parse XML responses into its PHP representation
+ */
+interface ParserInterface
+{
+    /**
+     * Parse XML string into PHP representation
+     *
+     * @param  string  $xmlString
+     * @param  boolean $isFault
+     * @return string
+     */
+    public function parse($xmlString, &$isFault);
+}
diff --git a/Classes/Library/fXmlRpc/Parser/XmlReaderParser.php b/Classes/Library/fXmlRpc/Parser/XmlReaderParser.php
new file mode 100644 (file)
index 0000000..73d1721
--- /dev/null
@@ -0,0 +1,359 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Parser;
+
+use fXmlRpc\Value\Base64;
+use XMLReader;
+use fXmlRpc\Exception\MissingExtensionException;
+use fXmlRpc\Exception\RuntimeException;
+use DateTime;
+use DateTimeZone;
+use DOMDocument;
+
+class XmlReaderParser implements ParserInterface
+{
+    public function __construct()
+    {
+        if (!extension_loaded('xmlreader')) {
+            throw MissingExtensionException::extensionMissing('xmlreader');
+        }
+    }
+
+    /**
+     * @throws RuntimeException
+     * {@inheritdoc}
+     */
+    public function parse($xmlString, &$isFault)
+    {
+        $useErrors = libxml_use_internal_errors(true);
+
+        $xml = new XMLReader();
+        $xml->xml($xmlString, 'UTF-8', LIBXML_COMPACT | LIBXML_NOCDATA | LIBXML_NOBLANKS);
+        $xml->setParserProperty(XMLReader::VALIDATE, false);
+        $xml->setParserProperty(XMLReader::LOADDTD, false);
+
+// This following assignments are auto-generated using fXmlRpc\CodeGenerator\XmlReaderParserBitmaskGenerator
+// Don’t edit manually
+        static $flagmethodResponse = 0b000000000000000000000000001;
+        static $flagparams = 0b000000000000000000000000010;
+        static $flagfault = 0b000000000000000000000000100;
+        static $flagparam = 0b000000000000000000000001000;
+        static $flagvalue = 0b000000000000000000000010000;
+        static $flagarray = 0b000000000000000000000100000;
+        static $flagmember = 0b000000000000000000001000000;
+        static $flagname = 0b000000000000000000010000000;
+        ${'flag#text'} = 0b000000000000000000100000000;
+        static $flagstring = 0b000000000000000001000000000;
+        static $flagstruct = 0b000000000000000010000000000;
+        static $flagint = 0b000000000000000100000000000;
+        static $flagbiginteger = 0b000000000000001000000000000;
+        static $flagi8 = 0b000000000000010000000000000;
+        static $flagi4 = 0b000000000000100000000000000;
+        static $flagi2 = 0b000000000001000000000000000;
+        static $flagi1 = 0b000000000010000000000000000;
+        static $flagboolean = 0b000000000100000000000000000;
+        static $flagdouble = 0b000000001000000000000000000;
+        static $flagfloat = 0b000000010000000000000000000;
+        static $flagbigdecimal = 0b000000100000000000000000000;
+        ${'flagdateTime.iso8601'} = 0b000001000000000000000000000;
+        static $flagdateTime = 0b000010000000000000000000000;
+        static $flagbase64 = 0b000100000000000000000000000;
+        static $flagnil = 0b001000000000000000000000000;
+        static $flagdom = 0b010000000000000000000000000;
+        static $flagdata = 0b100000000000000000000000000;
+// End of auto-generated code
+
+        $aggregates = [];
+        $depth = 0;
+        $nextExpectedElements = 0b000000000000000000000000001;
+        $i = 0;
+        while ($xml->read()) {
+            $i++;
+            $nodeType = $xml->nodeType;
+
+            if (($nodeType === XMLReader::COMMENT || $nodeType === XMLReader::DOC_TYPE) ||
+                (
+                   $nodeType === XMLReader::SIGNIFICANT_WHITESPACE &&
+                   ($nextExpectedElements & 0b000000000000000000100000000) !== 0b000000000000000000100000000)
+                ) {
+                continue;
+            }
+
+            if ($nodeType === XMLReader::ENTITY_REF) {
+                return '';
+            }
+
+            $tagName = $xml->localName;
+            if ($nextExpectedElements !== null &&
+                ($flag = isset(${'flag' . $tagName}) ? ${'flag' . $tagName} : -1) &&
+                ($nextExpectedElements & $flag) !== $flag) {
+                throw RuntimeException::unexpectedTag(
+                    $tagName,
+                    $nextExpectedElements,
+                    get_defined_vars(),
+                    $xml->depth,
+                    $xml->readOuterXml()
+                );
+            }
+
+            PROCESSING:
+            switch ($nodeType) {
+                case XMLReader::ELEMENT:
+                    switch ($tagName) {
+                        case 'methodResponse':
+                            // Next: params, fault
+                            $nextExpectedElements = 0b000000000000000000000000110;
+                            break;
+
+                        case 'params':
+                            // Next: param
+                            $nextExpectedElements = 0b000000000000000000000001000;
+                            $aggregates[$depth] = [];
+                            $isFault = false;
+                            break;
+
+                        case 'fault':
+                            $isFault = true;
+                            // Break intentionally omitted
+                        case 'param':
+                            // Next: value
+                            $nextExpectedElements = 0b000000000000000000000010000;
+                            break;
+
+                        case 'array':
+                            $aggregates[++$depth] = [];
+                            // Break intentionally omitted
+                        case 'data':
+                            // Next: array, data, value
+                            $nextExpectedElements = 0b100000000000000000000110000;
+                            break;
+
+                        case 'struct':
+                            // Next: struct, member, value
+                            $nextExpectedElements = 0b000000000000000010001010000;
+                            $aggregates[++$depth] = [];
+                            break;
+
+                        case 'member':
+                            // Next: name, value
+                            $nextExpectedElements = 0b000000000000000000010010000;
+                            $aggregates[++$depth] = [];
+                            break;
+
+                        case 'name':
+                            // Next: #text
+                            $nextExpectedElements = 0b000000000000000000100000000;
+                            $type = 'name';
+                            break;
+
+                        case 'value':
+                            $nextExpectedElements = 0b011111111111111111100100000;
+                            $type = 'value';
+                            break;
+
+                        case 'base64':
+                        case 'string':
+                        case 'biginteger':
+                        case 'i8':
+                        case 'dateTime.iso8601':
+                        case 'dateTime':
+                            // Next: value, $tagName, #text
+                            $nextExpectedElements = 0b000000000000000000100010000 | ${'flag' . $tagName};
+                            $type = $tagName;
+                            $aggregates[$depth + 1] = '';
+                            break;
+
+                        case 'nil':
+                            // Next: value, $tagName
+                            $nextExpectedElements = 0b001000000000000000000010000 | ${'flag' . $tagName};
+                            $type = $tagName;
+                            $aggregates[$depth + 1] = null;
+                            break;
+
+                        case 'int':
+                        case 'i4':
+                        case 'i2':
+                        case 'i1':
+                            // Next: value, #text, $tagName
+                            $nextExpectedElements = 0b000000000000000000100010000 | ${'flag' . $tagName};
+                            $type = $tagName;
+                            $aggregates[$depth + 1] = 0;
+                            break;
+
+                        case 'boolean':
+                            // Next: value, #text, $tagName
+                            $nextExpectedElements = 0b000000000000000000100010000 | ${'flag' . $tagName};
+                            $type = 'boolean';
+                            $aggregates[$depth + 1] = false;
+                            break;
+
+                        case 'double':
+                        case 'float':
+                        case 'bigdecimal':
+                            // Next: value, #text, $tagName
+                            $nextExpectedElements = 0b000000000000000000100010000 | ${'flag' . $tagName};
+                            $type = $tagName;
+                            $aggregates[$depth + 1] = 0.0;
+                            break;
+
+                        case 'dom':
+                            $type = 'dom';
+                            // Disable type checking
+                            $nextExpectedElements = null;
+                            $aggregates[$depth + 1] = $xml->readInnerXml();
+                            break;
+                    }
+                    break;
+
+                case XMLReader::END_ELEMENT:
+                    switch ($tagName) {
+                        case 'params':
+                        case 'fault':
+                            break 3;
+
+                        case 'param':
+                            // Next: params, param
+                            $nextExpectedElements = 0b000000000000000000000001010;
+                            break;
+
+                        case 'value':
+                            $nextExpectedElements = 0b100100000011100100011011100;
+                            $aggregates[$depth][] = $aggregates[$depth + 1];
+                            break;
+
+                        case 'array':
+                        case 'struct':
+                            --$depth;
+                            // Break intentionally omitted
+                        case 'string':
+                        case 'int':
+                        case 'biginteger':
+                        case 'i8':
+                        case 'i4':
+                        case 'i2':
+                        case 'i1':
+                        case 'boolean':
+                        case 'double':
+                        case 'float':
+                        case 'bigdecimal':
+                        case 'dateTime.iso8601':
+                        case 'dateTime':
+                        case 'base64':
+                        case 'nil':
+                            // Next: value
+                            $nextExpectedElements = 0b000000000000000000000010000;
+                            break;
+
+                        case 'data':
+                            // Next: array
+                            $nextExpectedElements = 0b000000000000000000000100000;
+                            break;
+
+                        case 'name':
+                            // Next: value, member
+                            $nextExpectedElements = 0b000000000000000000001010000;
+                            $aggregates[$depth]['name'] = $aggregates[$depth + 1];
+                            break;
+
+                        case 'member':
+                            // Next: struct, member
+                            $nextExpectedElements = 0b000000000000000010001000000;
+                            $aggregates[$depth - 1][$aggregates[$depth]['name']] = $aggregates[$depth][0];
+                            unset($aggregates[$depth], $aggregates[$depth + 1]);
+                            --$depth;
+                            break;
+                    }
+                    break;
+
+                case XMLReader::TEXT:
+                case XMLReader::SIGNIFICANT_WHITESPACE:
+                    switch ($type) {
+                        case 'int':
+                        case 'i4':
+                        case 'i2':
+                        case 'i1':
+                            $value = (int) $xml->value;
+                            break;
+
+                        case 'boolean':
+                            $value = $xml->value === '1';
+                            break;
+
+                        case 'double':
+                        case 'float':
+                        case 'bigdecimal':
+                            $value = (float) $xml->value;
+                            break;
+
+                        case 'dateTime.iso8601':
+                            $value = DateTime::createFromFormat(
+                                'Ymd\TH:i:s',
+                                $xml->value,
+                                isset($timezone) ? $timezone : $timezone = new DateTimeZone('UTC')
+                            );
+                            break;
+
+                        case 'dateTime':
+                            $value = DateTime::createFromFormat(
+                                'Y-m-d\TH:i:s.uP',
+                                $xml->value,
+                                isset($timezone) ? $timezone : $timezone = new DateTimeZone('UTC')
+                            );
+                            break;
+
+                        case 'base64':
+                            $value = Base64::deserialize($xml->value);
+                            break;
+
+                        case 'dom':
+                            $doc = new DOMDocument('1.0', 'UTF-8');
+                            $doc->loadXML($aggregates[$depth + 1]);
+                            $value = $doc;
+                            break;
+
+                        default:
+                            $value = &$xml->value;
+                            break;
+                    }
+
+                    $aggregates[$depth + 1] = $value;
+                    if ($nextExpectedElements === null) {
+                        break;
+                    }
+                    // Next: any
+                    $nextExpectedElements = 0b111111111111111111111111111;
+                    break;
+            }
+
+            if ($xml->isEmptyElement && $nodeType !== XMLReader::END_ELEMENT) {
+                $nodeType = XMLReader::END_ELEMENT;
+                goto PROCESSING;
+            }
+        }
+
+        libxml_use_internal_errors($useErrors);
+
+        return $aggregates ? array_pop($aggregates[0]) : null;
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Proxy.php b/Classes/Library/fXmlRpc/Proxy.php
new file mode 100644 (file)
index 0000000..2cdea0e
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc;
+
+class Proxy
+{
+    /**
+     * @var ClientInterface
+     */
+    private $client;
+
+    /**
+     * @var string
+     */
+    private $namespace;
+
+    /**
+     * @var string
+     */
+    private $namespaceSeparator = '.';
+
+    /**
+     * @var Proxy[string]
+     */
+    private $proxies = [];
+
+    /**
+     * @param ClientInterface $client
+     * @param string          $namespaceSeparator
+     * @param string          $namespace
+     */
+    public function __construct(ClientInterface $client, $namespaceSeparator = '.', $namespace = null)
+    {
+        $this->client = $client;
+        $this->namespaceSeparator = $namespaceSeparator;
+        $this->namespace = $namespace;
+    }
+
+    /**
+     * Invokes remote command
+     *
+     * @param  string $method
+     * @param  array  $parameters
+     * @return mixed
+     */
+    public function __call($method, array $parameters)
+    {
+        return $this->client->call($this->prependNamespace($method), $parameters);
+    }
+
+    /**
+     * Returns namespace specific Proxy instance
+     *
+     * @param  string $namespace
+     * @return Proxy
+     */
+    public function __get($namespace)
+    {
+        $namespace = $this->prependNamespace($namespace);
+        if (!isset($this->proxies[$namespace])) {
+            $this->proxies[$namespace] = new static($this->client, $this->namespaceSeparator, $namespace);
+        }
+
+        return $this->proxies[$namespace];
+    }
+
+    /**
+     * Prepend namespace if set
+     *
+     * @param  string $string
+     * @return string
+     */
+    protected function prependNamespace($string)
+    {
+        if ($this->namespace === null) {
+            return $string;
+        }
+
+        return $this->namespace . $this->namespaceSeparator . $string;
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Serializer/NativeSerializer.php b/Classes/Library/fXmlRpc/Serializer/NativeSerializer.php
new file mode 100644 (file)
index 0000000..535e0c1
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Serializer;
+
+use DateTime;
+use fXmlRpc\Value\Base64Interface;
+use fXmlRpc\Exception\SerializationException;
+use fXmlRpc\Exception\MissingExtensionException;
+
+class NativeSerializer implements SerializerInterface
+{
+    public function __construct()
+    {
+        if (!extension_loaded('xmlrpc')) {
+            throw MissingExtensionException::extensionMissing('xmlrpc');
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function serialize($method, array $params = [])
+    {
+        $toBeVisited = [&$params];
+        while (isset($toBeVisited[0]) && $value = &$toBeVisited[0]) {
+
+            $type = gettype($value);
+            if ($type === 'array') {
+                foreach ($value as &$child) {
+                    $toBeVisited[] = &$child;
+                }
+
+            } elseif ($type === 'object') {
+                if ($value instanceof DateTime) {
+                    $value = $value->format('Ymd\TH:i:s');
+                    xmlrpc_set_type($value, 'datetime');
+                } elseif ($value instanceof Base64Interface) {
+                    $value = $value->getDecoded();
+                    xmlrpc_set_type($value, 'base64');
+                } else {
+                    $value = get_object_vars($value);
+                }
+            } elseif ($type === 'resource') {
+                throw SerializationException::invalidType($value);
+            }
+
+            array_shift($toBeVisited);
+        }
+
+        return xmlrpc_encode_request(
+            $method,
+            $params,
+            ['encoding' => 'UTF-8', 'escaping' => 'markup', 'verbosity' => 'no_white_space']
+        );
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Serializer/SerializerInterface.php b/Classes/Library/fXmlRpc/Serializer/SerializerInterface.php
new file mode 100644 (file)
index 0000000..97a6969
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Serializer;
+
+/**
+ * Serializer creates XML from native PHP types
+ */
+interface SerializerInterface
+{
+    /**
+     * Serialize XML/RPC method name and params into XML representation
+     *
+     * @param  string $method
+     * @param  array  $params
+     * @return string
+     */
+    public function serialize($method, array $params = []);
+}
diff --git a/Classes/Library/fXmlRpc/Serializer/XmlWriterSerializer.php b/Classes/Library/fXmlRpc/Serializer/XmlWriterSerializer.php
new file mode 100644 (file)
index 0000000..5a09269
--- /dev/null
@@ -0,0 +1,221 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Serializer;
+
+use XMLWriter;
+use Closure;
+use DateTime;
+use fXmlRpc\Value\Base64Interface;
+use fXmlRpc\ExtensionSupportInterface;
+use fXmlRpc\Exception\SerializationException;
+use fXmlRpc\Exception\MissingExtensionException;
+
+class XmlWriterSerializer implements SerializerInterface, ExtensionSupportInterface
+{
+    /**
+     * @var XMLWriter
+     */
+    private $writer;
+
+    /**
+     * @var array
+     */
+    private $extensions = [];
+
+    public function __construct()
+    {
+        if (!extension_loaded('xmlwriter')) {
+            throw MissingExtensionException::extensionMissing('xmlwriter');
+        }
+
+        $this->writer = new XMLWriter();
+        $this->writer->openMemory();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function enableExtension($extension)
+    {
+        $this->extensions[$extension] = true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function disableExtension($extension)
+    {
+        $this->extensions[$extension] = false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isExtensionEnabled($extension)
+    {
+        return isset($this->extensions[$extension]) ? $this->extensions[$extension] : true;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function serialize($methodName, array $params = [])
+    {
+        $writer = $this->writer;
+
+        $writer->startDocument('1.0', 'UTF-8');
+        $writer->startElement('methodCall');
+        $writer->writeElement('methodName', $methodName);
+        $writer->startElement('params');
+
+        $endNode = static function () use ($writer) {
+            $writer->endElement();
+        };
+        $valueNode = static function () use ($writer) {
+            $writer->startElement('value');
+        };
+        $paramNode = static function () use ($writer) {
+            $writer->startElement('param');
+        };
+
+        $toBeVisited = [];
+        foreach (array_reverse($params) as $param) {
+            $toBeVisited[] = $endNode;
+            $toBeVisited[] = $param;
+            $toBeVisited[] = $paramNode;
+        }
+
+        $nilTagName = $this->isExtensionEnabled(ExtensionSupportInterface::EXTENSION_NIL) ? 'nil' : 'string';
+
+        while ($toBeVisited) {
+            $node = array_pop($toBeVisited);
+            $type = gettype($node);
+
+            if ($type === 'string') {
+                $writer->startElement('value');
+                $writer->writeElement('string', $node);
+                $writer->endElement();
+
+            } elseif ($type === 'integer') {
+                $writer->startElement('value');
+                $writer->writeElement('int', $node);
+                $writer->endElement();
+
+            } elseif ($type === 'double') {
+                if (!isset($precision)) {
+                    $precision = ini_get('precision');
+                }
+
+                $writer->startElement('value');
+                $writer->writeElement('double', $node);
+                $writer->endElement();
+
+            } elseif ($type === 'boolean') {
+                $writer->startElement('value');
+                $writer->writeElement('boolean', $node ? '1' : '0');
+                $writer->endElement();
+
+            } elseif ($type === 'NULL') {
+                $writer->startElement('value');
+                $writer->writeElement($nilTagName);
+                $writer->endElement();
+
+            } elseif ($type === 'array') {
+                /** Find out if it is a struct or an array */
+                $min = 0;
+                foreach ($node as $min => &$child) {
+                    break;
+                }
+                $isStruct = false;
+                $length = count($node) + $min;
+                for ($a = $min; $a < $length; ++$a) {
+                    if (!isset($node[$a])) {
+                        $isStruct = true;
+                        break;
+                    }
+                }
+
+                if (!$isStruct) {
+                    $toBeVisited[] = $endNode;
+                    $toBeVisited[] = $endNode;
+                    $toBeVisited[] = $endNode;
+                    foreach (array_reverse($node) as $value) {
+                        $toBeVisited[] = $value;
+                    }
+                    $toBeVisited[] = static function () use ($writer) {
+                        $writer->startElement('array');
+                        $writer->startElement('data');
+                    };
+                    $toBeVisited[] = $valueNode;
+
+                } else {
+                    struct:
+                    $toBeVisited[] = $endNode;
+                    $toBeVisited[] = $endNode;
+                    foreach (array_reverse($node, true) as $key => $value) {
+                        $toBeVisited[] = $endNode;
+                        $toBeVisited[] = $value;
+                        $toBeVisited[] = static function () use ($writer, $key) {
+                            $writer->writeElement('name', $key);
+                        };
+                        $toBeVisited[] = static function () use ($writer) {
+                            $writer->startElement('member');
+                        };
+                    }
+                    $toBeVisited[] = static function () use ($writer) {
+                        $writer->startElement('struct');
+                    };
+                    $toBeVisited[] = $valueNode;
+                }
+
+            } elseif ($type === 'object') {
+
+                if ($node instanceof Closure) {
+                    $node();
+
+                } elseif ($node instanceof DateTime) {
+                    $writer->startElement('value');
+                    $writer->writeElement('dateTime.iso8601', $node->format('Ymd\TH:i:s'));
+                    $writer->endElement();
+
+                } elseif ($node instanceof Base64Interface) {
+                    $writer->startElement('value');
+                    $writer->writeElement('base64', $node->getEncoded() . "\n");
+                    $writer->endElement();
+
+                } else {
+                    $node = get_object_vars($node);
+                    goto struct;
+                }
+            } elseif ($type === 'resource') {
+                throw SerializationException::invalidType($node);
+            }
+        }
+
+        $writer->endElement();
+        $writer->endElement();
+
+        return $writer->flush(true);
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Timing/AbstractTimerBridge.php b/Classes/Library/fXmlRpc/Timing/AbstractTimerBridge.php
new file mode 100644 (file)
index 0000000..07cb371
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Timing;
+
+/**
+ * Base class for timing bridges
+ *
+ * Base class for bridging between timing information and various logger
+ * implementations.
+ */
+abstract class AbstractTimerBridge implements TimerInterface
+{
+    /**
+     * @var object
+     */
+    protected $logger;
+
+    /**
+     * @var array|integer
+     */
+    protected $level;
+
+    /**
+     * @var string
+     */
+    protected $messageTemplate = 'fXmlRpc call took %01.10Fs';
+
+    /**
+     * Set log level
+     *
+     * @param mixed $level
+     * @param mixed $default
+     */
+    protected function setLevel($level, $default)
+    {
+        if (is_array($level)) {
+            krsort($level);
+        }
+
+        $this->level = $level ?: $default;
+    }
+
+    /**
+     * Get log level by callTime
+     *
+     * @param  float $callTime
+     * @return integer
+     */
+    protected function getLevel($callTime)
+    {
+        if (!is_array($this->level)) {
+            return $this->level;
+        }
+
+        foreach ($this->level as $threshold => $level) {
+            if ($callTime >= $threshold) {
+                return $level;
+            }
+        }
+
+        return $level;
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Timing/MonologTimerBridge.php b/Classes/Library/fXmlRpc/Timing/MonologTimerBridge.php
new file mode 100644 (file)
index 0000000..46bb63a
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Timing;
+
+use Monolog\Logger;
+
+class MonologTimerBridge extends AbstractTimerBridge
+{
+    /**
+     * Create new monolog bridge
+     *
+     * Allows passing custom log level and message template (with sprintf() control characters) for log message
+     * customization
+     *
+     * @param Logger     $logger
+     * @param null|array $level
+     * @param null       $messageTemplate
+     */
+    public function __construct(Logger $logger, $level = null, $messageTemplate = null)
+    {
+        $this->logger = $logger;
+        $this->setLevel($level, Logger::DEBUG);
+        $this->messageTemplate = $messageTemplate ?: $this->messageTemplate;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function recordTiming($callTime, $method, array $arguments)
+    {
+        $level = $this->getLevel($callTime);
+
+        $this->logger->addRecord(
+            $level,
+            sprintf($this->messageTemplate, $callTime),
+            ['xmlrpcMethod' => $method, 'xmlrpcArguments' => $arguments]
+        );
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Timing/Psr3TimerBridge.php b/Classes/Library/fXmlRpc/Timing/Psr3TimerBridge.php
new file mode 100644 (file)
index 0000000..60490e6
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Timing;
+
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+
+class Psr3TimerBridge extends AbstractTimerBridge
+{
+    /**
+     * Create new bridge or a PSR-3 compatible logger
+     *
+     * Allows passing custom log level and message template (with sprintf() control characters) for log message
+     * customization
+     *
+     * @param LoggerInterface $logger
+     * @param integer         $level
+     * @param string          $messageTemplate
+     */
+    public function __construct(LoggerInterface $logger, $level = null, $messageTemplate = null)
+    {
+        $this->logger = $logger;
+        $this->setLevel($level, LogLevel::DEBUG);
+        $this->messageTemplate = $messageTemplate ?: $this->messageTemplate;
+    }
+
+    public function recordTiming($callTime, $method, array $arguments)
+    {
+        $this->logger->log(
+            $this->getLevel($callTime),
+            sprintf($this->messageTemplate, $callTime),
+            ['xmlrpcMethod' => $method, 'xmlrpcArguments' => $arguments]
+        );
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Timing/TimerInterface.php b/Classes/Library/fXmlRpc/Timing/TimerInterface.php
new file mode 100644 (file)
index 0000000..59d7c30
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Timing;
+
+interface TimerInterface
+{
+    /**
+     * Records a timing information
+     *
+     * @param float  $callTime
+     * @param string $method
+     * @param array  $arguments
+     * @return null
+     */
+    public function recordTiming($callTime, $method, array $arguments);
+}
diff --git a/Classes/Library/fXmlRpc/Timing/TimingDecorator.php b/Classes/Library/fXmlRpc/Timing/TimingDecorator.php
new file mode 100644 (file)
index 0000000..0427c06
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Timing;
+
+use fXmlRpc\ClientInterface;
+use fXmlRpc\AbstractDecorator;
+use fXmlRpc\Timing\TimerInterface;
+
+class TimingDecorator extends AbstractDecorator
+{
+    /**
+     * @var TimerInterface
+     */
+    private $timer;
+
+    /**
+     * Create new client decorator to record timing information
+     *
+     * @param ClientInterface $wrapped
+     * @param TimerInterface  $timer
+     */
+    public function __construct(ClientInterface $wrapped, TimerInterface $timer)
+    {
+        parent::__construct($wrapped);
+        $this->timer = $timer;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function call($methodName, array $arguments = [])
+    {
+        $startTime = microtime(true);
+        $result = parent::call($methodName, $arguments);
+        $this->timer->recordTiming(microtime(true) - $startTime, $methodName, $arguments);
+
+        return $result;
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Timing/ZendFrameworkOneTimerBridge.php b/Classes/Library/fXmlRpc/Timing/ZendFrameworkOneTimerBridge.php
new file mode 100644 (file)
index 0000000..92b06dd
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+namespace fXmlRpc\Timing;
+
+use Zend_Log as Log;
+
+class ZendFrameworkOneTimerBridge extends AbstractTimerBridge
+{
+    /**
+     * Create new Zend_Log bridge
+     *
+     * Allows passing custom log level and message template (with sprintf() control characters) for log message
+     * customization
+     *
+     * @param Log $logger
+     * @param integer  $level
+     * @param string   $messageTemplate
+     */
+    public function __construct(Log $logger, $level = null, $messageTemplate = null)
+    {
+        $this->logger = $logger;
+        $this->setLevel($level, Log::DEBUG);
+        $this->messageTemplate = $messageTemplate ?: $this->messageTemplate;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function recordTiming($callTime, $method, array $arguments)
+    {
+        $this->logger->log(
+            sprintf($this->messageTemplate, $callTime),
+            $this->getLevel($callTime),
+            ['xmlrpcMethod' => $method, 'xmlrpcArguments' => $arguments]
+        );
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Timing/ZendFrameworkTwoTimerBridge.php b/Classes/Library/fXmlRpc/Timing/ZendFrameworkTwoTimerBridge.php
new file mode 100644 (file)
index 0000000..f8884e7
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+namespace fXmlRpc\Timing;
+
+use Zend\Log\LoggerInterface;
+
+class ZendFrameworkTwoTimerBridge extends AbstractTimerBridge
+{
+    /**
+     * Create new Zend\Log\LoggerInterface bridge
+     *
+     * Allows passing custom log level and message template (with sprintf() control characters) for log message
+     * customization
+     *
+     * @param LoggerInterface $logger
+     * @param string          $method
+     * @param string          $messageTemplate
+     */
+    public function __construct(LoggerInterface $logger, $method = null, $messageTemplate = null)
+    {
+        $this->logger = $logger;
+        $this->setLevel($method, 'debug');
+        $this->messageTemplate = $messageTemplate ?: $this->messageTemplate;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function recordTiming($callTime, $method, array $arguments)
+    {
+        $level = $this->getLevel($callTime);
+        $this->logger->{$level}(
+            sprintf($this->messageTemplate, $callTime),
+            ['xmlrpcMethod' => $method, 'xmlrpcArguments' => $arguments]
+        );
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Transport/BuzzBrowserBridge.php b/Classes/Library/fXmlRpc/Transport/BuzzBrowserBridge.php
new file mode 100644 (file)
index 0000000..aaf3c2a
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Transport;
+
+use Buzz\Browser;
+use Buzz\Message\Response;
+use RuntimeException;
+use fXmlRpc\Exception\TcpException;
+use fXmlRpc\Exception\HttpException;
+
+class BuzzBrowserBridge implements TransportInterface
+{
+    /**
+     * @var Browser
+     */
+    private $browser;
+
+    public function __construct(Browser $browser)
+    {
+        $this->browser = $browser;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function send($uri, $payload)
+    {
+        try {
+            /** @var $response Response */
+            $response = $this->browser->post($uri, [], $payload);
+        } catch (RuntimeException $e) {
+            throw TcpException::transportError($e);
+        }
+
+        if ($response->getStatusCode() !== 200) {
+            throw HttpException::httpError($response->getReasonPhrase(), $response->getStatusCode());
+        }
+
+        return $response->getContent();
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Transport/CurlTransport.php b/Classes/Library/fXmlRpc/Transport/CurlTransport.php
new file mode 100644 (file)
index 0000000..9227a54
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * cryptocompress <cryptocompress@googlemail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Transport;
+
+use fXmlRpc\Exception\HttpException;
+use fXmlRpc\Exception\TcpException;
+
+class CurlTransport implements TransportInterface
+{
+    /**
+     * @var resource
+     */
+    protected $handle;
+
+    public function __construct()
+    {
+        $this->handle = curl_init();
+
+        curl_setopt_array(
+            $this->handle,
+            [
+                CURLOPT_HTTPHEADER        => ['Content-Type: text/xml'],
+                CURLOPT_RETURNTRANSFER    => true,
+                CURLOPT_HEADER            => true,
+                CURLOPT_MAXREDIRS         => 5,
+                CURLOPT_TIMEOUT_MS        => 5000,
+                CURLOPT_CONNECTTIMEOUT_MS => 5000,
+                CURLOPT_POST              => true,
+            ]
+        );
+    }
+
+    public function __destruct()
+    {
+        if (is_resource($this->handle)) {
+            curl_close($this->handle);
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function send($uri, $payload)
+    {
+        curl_setopt($this->handle, CURLOPT_URL, $uri);
+        curl_setopt($this->handle, CURLOPT_POSTFIELDS, $payload);
+
+        $response = curl_exec($this->handle);
+        if ($response === false || strlen($response) < 1) {
+            throw TcpException::transportError(curl_error($this->handle));
+        }
+
+        $code = curl_getinfo($this->handle, CURLINFO_HTTP_CODE);
+        if ($code !== 200) {
+            throw HttpException::httpError(curl_error($this->handle), $code);
+        }
+
+        return substr($response, curl_getinfo($this->handle, CURLINFO_HEADER_SIZE));
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Transport/GuzzleBridge.php b/Classes/Library/fXmlRpc/Transport/GuzzleBridge.php
new file mode 100644 (file)
index 0000000..43fb746
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Transport;
+
+use Guzzle\Http\Client;
+use Guzzle\Http\Message\BadResponseException;
+use Guzzle\Http\Exception\ClientErrorResponseException;
+use Guzzle\Http\Exception\ServerErrorResponseException;
+use Guzzle\Http\Curl\CurlException as CompatCurlException;
+use Guzzle\Http\Exception\CurlException;
+use fXmlRpc\Exception\HttpException;
+use fXmlRpc\Exception\TcpException;
+
+class GuzzleBridge implements TransportInterface
+{
+    /**
+     * @var Client
+     */
+    private $client;
+
+    /**
+     * @param Client $client
+     */
+    public function __construct(Client $client)
+    {
+        $this->client = $client;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function send($uri, $payload)
+    {
+        try {
+            $response = $this->client->post($uri, null, $payload)
+                                     ->send();
+        } catch (CurlException $e) {
+            throw TcpException::transportError($e);
+        } catch (CompatCurlException $e) {
+            throw TcpException::transportError($e);
+        } catch (BadResponseException $e) {
+            throw HttpException::httpError($e->getMessage(), $e->getResponse()->getStatusCode(), $e);
+        } catch (ServerErrorResponseException $e) {
+            throw HttpException::httpError($e->getMessage(), $e->getResponse()->getStatusCode(), $e);
+        } catch (ClientErrorResponseException $e) {
+            throw HttpException::httpError($e->getMessage(), $e->getResponse()->getStatusCode(), $e);
+        }
+
+        return $response->getBody(true);
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Transport/PeclHttpBridge.php b/Classes/Library/fXmlRpc/Transport/PeclHttpBridge.php
new file mode 100644 (file)
index 0000000..6e63a99
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Transport;
+
+use HttpRequest;
+use HttpInvalidParamException;
+use fXmlRpc\Exception\HttpException;
+use fXmlRpc\Exception\TcpException;
+use ReflectionExtension;
+
+class PeclHttpBridge implements TransportInterface
+{
+    /**
+     * @var HttpRequest
+     */
+    private $request;
+
+    /**
+     * @param HttpRequest $request
+     */
+    public function __construct(HttpRequest $request)
+    {
+        $this->request = $request;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function send($uri, $payload)
+    {
+        try {
+            $this->request->setUrl($uri);
+            $this->request->setMethod(HttpRequest::METH_POST);
+            $extension = new ReflectionExtension('http');
+            if (version_compare($extension->getVersion(), '1.5.0', '>=')) {
+                $this->request->setBody($payload);
+            } else {
+                $this->request->setRawPostData($payload);
+            }
+            $response = $this->request->send();
+
+            if ($response->getResponseCode() !== 200) {
+                throw HttpException::httpError($response->getResponseStatus(), $response->getResponseCode());
+            }
+
+            return $response->getBody();
+        } catch (HttpInvalidParamException $e) {
+            throw TcpException::transportError($e);
+        }
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Transport/StreamSocketTransport.php b/Classes/Library/fXmlRpc/Transport/StreamSocketTransport.php
new file mode 100644 (file)
index 0000000..a481436
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Transport;
+
+use fXmlRpc\Exception\HttpException;
+use fXmlRpc\Exception\TcpException;
+
+class StreamSocketTransport implements TransportInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function send($uri, $payload)
+    {
+        $context = stream_context_create(
+            [
+                'http' => [
+                    'method'  => 'POST',
+                    'header'  => 'Content-Type: text/xml',
+                    'content' => $payload,
+                ]
+            ]
+        );
+/**
+ *   @todo require Comments    
+ */
+        $response = @file_get_contents($uri, false, $context);
+        if ($response === false) {
+            $error = error_get_last();
+
+            if (strpos($error['message'], 'HTTP request failed')) {
+                $matched = preg_match('|HTTP/1.[0-1]\s+(?<code>\d+)|', $error['message'], $matches);
+                throw HttpException::httpError($error['message'], $matched ? $matches['code'] : null);
+            }
+
+            throw TcpException::transportError($error['message']);
+        }
+
+        return $response;
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Transport/TransportInterface.php b/Classes/Library/fXmlRpc/Transport/TransportInterface.php
new file mode 100644 (file)
index 0000000..c75dbe0
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Transport;
+
+use fXmlRpc\Exception\HttpException;
+use fXmlRpc\Exception\TransportException;
+
+/**
+ * Transport interface
+ *
+ * This interface is implemented by transports to provide means to send
+ * requests over the wire.
+ */
+interface TransportInterface
+{
+    /**
+     * Send XML/RPC request
+     *
+     * @param  string             $uri
+     * @param  string             $payload
+     * @throws HttpException      If an HTTP exception occurred
+     * @throws TransportException If a transport error occurred
+     * @return string
+     */
+    public function send($uri, $payload);
+}
diff --git a/Classes/Library/fXmlRpc/Transport/ZendFrameworkOneHttpClientBridge.php b/Classes/Library/fXmlRpc/Transport/ZendFrameworkOneHttpClientBridge.php
new file mode 100644 (file)
index 0000000..552564d
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Transport;
+
+use Zend_Http_Client as HttpClient;
+use Zend_Http_Client_Adapter_Exception as HttpClientAdapterException;
+use Zend_Http_Client_Exception as HttpClientException;
+use fXmlRpc\Exception\HttpException;
+use fXmlRpc\Exception\TcpException;
+
+class ZendFrameworkOneHttpClientBridge implements TransportInterface
+{
+    /**
+     * @var HttpClient
+     */
+    private $client;
+
+    /**
+     * @param HttpClient $client
+     */
+    public function __construct(HttpClient $client)
+    {
+        $this->client = $client;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function send($url, $payload)
+    {
+        try {
+            $response = $this->client
+                ->setUri($url)
+                ->setRawData($payload)
+                ->request('POST');
+        } catch (HttpClientAdapterException $e) {
+            throw TcpException::transportError($e);
+        } catch (HttpClientException $e) {
+            throw TcpException::transportError($e);
+        }
+
+        if ($response->getStatus() !== 200) {
+            throw HttpException::httpError($response->getMessage(), $response->getStatus());
+        }
+
+        return $response->getBody();
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Transport/ZendFrameworkTwoHttpClientBridge.php b/Classes/Library/fXmlRpc/Transport/ZendFrameworkTwoHttpClientBridge.php
new file mode 100644 (file)
index 0000000..ac53d86
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Transport;
+
+use Zend\Http\Client;
+use Zend\Http\Client\Adapter\Exception\RuntimeException;
+use fXmlRpc\Exception\HttpException;
+use fXmlRpc\Exception\TcpException;
+
+class ZendFrameworkTwoHttpClientBridge implements TransportInterface
+{
+    /**
+     * @var Client
+     */
+    private $client;
+
+    /**
+     * @param Client $client
+     */
+    public function __construct(Client $client)
+    {
+        $this->client = $client;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function send($url, $payload)
+    {
+        try {
+            $response = $this->client
+                ->setMethod('POST')
+                ->setUri($url)
+                ->setRawBody($payload)
+                ->send();
+        } catch (RuntimeException $e) {
+            throw TcpException::transportError($e);
+        }
+
+        if ($response->getStatusCode() !== 200) {
+            throw HttpException::httpError($response->getReasonPhrase(), $response->getStatusCode());
+        }
+
+        return $response->getBody();
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Value/Base64.php b/Classes/Library/fXmlRpc/Value/Base64.php
new file mode 100644 (file)
index 0000000..263a2cc
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Value;
+
+final class Base64 implements Base64Interface
+{
+    /**
+     * @var string
+     */
+    private $encoded;
+
+    /**
+     * @var string
+     */
+    private $decoded;
+
+    /**
+     * @param string $encoded
+     * @param string $decoded
+     */
+    private function __construct($encoded, $decoded)
+    {
+        $this->encoded = $encoded;
+        $this->decoded = $decoded;
+    }
+
+    /**
+     * Return new base64 value object by encoded value
+     *
+     * @param  string $string
+     * @return Base64
+     */
+    public static function serialize($string)
+    {
+        $value = new static(null, $string);
+
+        return $value;
+    }
+
+    /**
+     * Return new base64 value by string
+     *
+     * @param  string $value
+     * @return Base64
+     */
+    public static function deserialize($value)
+    {
+        $value = new static(trim($value), null);
+
+        return $value;
+    }
+
+    /**
+     * Get bas64 value as base64 string
+     *
+     * @return string
+     */
+    public function getEncoded()
+    {
+        if ($this->encoded === null) {
+            $this->encoded = base64_encode($this->decoded);
+        }
+
+        return $this->encoded;
+    }
+
+    /**
+     * Get base64 value as string
+     *
+     * @return string
+     */
+    public function getDecoded()
+    {
+        if ($this->decoded === null) {
+            $this->decoded = base64_decode($this->encoded);
+        }
+
+        return $this->decoded;
+    }
+}
diff --git a/Classes/Library/fXmlRpc/Value/Base64Interface.php b/Classes/Library/fXmlRpc/Value/Base64Interface.php
new file mode 100644 (file)
index 0000000..1450132
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Copyright (C) 2012-2013
+ * Lars Strojny, InterNations GmbH <lars.strojny@internations.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+namespace fXmlRpc\Value;
+
+interface Base64Interface
+{
+    public function getEncoded();
+
+    public function getDecoded();
+}
diff --git a/Classes/Service/PingbackClient.php b/Classes/Service/PingbackClient.php
new file mode 100644 (file)
index 0000000..2325607
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+namespace PHTH\Pongback\Service;
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/**
+ * Description of RequestPingback
+ *
+ * @author Michael
+           */
+   
+class PingbackClient {
+   
+    /**
+     *
+     * @var string $targetLink
+     */
+    protected $targetLink;
+    
+    public function getTargetLink() {
+        return $this->targetLink;
+    }
+
+    public function setTargetLink($targetLink) {
+        $this->targetLink = $targetLink;
+    }
+    
+
+
+    public function mailPingbackArrived(&$params){
+      
+        $sourceLink = $params['params'][1];
+
+        /**
+         * An Hook from PingbackController
+         * 
+         * require  [defaultMailFromAddress] and [defaultMailFromName]
+         */
+        $pongbackConf = (array) unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['pongback']);
+        if(\TYPO3\CMS\Core\Utility\GeneralUtility::validEmail($pongbackConf['notificationAddress'])){
+            $mailer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Mail\\MailMessage');
+
+            $subject = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tx_pongback_domain_model_pingback.pingback_arrived_alert_mail_subject", 'pongback');
+            $body = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate("tx_pongback_domain_model_pingback.pingback_arrived_alert_mail", 'pongback') . " $sourceLink ";
+
+            $from = \TYPO3\CMS\Core\Utility\MailUtility::getSystemFrom();
+
+            $mailer->setFrom($from);
+            $mailer->setTo(array($pongbackConf['notificationAddress'] => 'mail'))
+                    ->setSubject($subject)
+                    ->setBody($body);
+
+
+            $mailer->send();
+        }
+    }
+          
+      /**
+  * 
+  * @param type $targetUri
+  * @param type $sourceUri 
+  */
+        
+    public function send($targetUri,$sourceUri){
+        
+        $this->autoDiscovery($targetUri);
+        
+        $client = new \fXmlRpc\Client($this->getTargetLink()); 
+        $response = $client->call("pingback.ping" ,array($sourceUri,$targetUri)); 
+      
+    
+    }  
+      /**
+     *   Pingback send Autodiscovery 
+     *  @return string URL + xmlrpc.php 
+     */
+     public function autoDiscovery($targetLink){
+            $searchPattern = '/X-Pingback/'; 
+            $proofLink = $this->sendRequest($targetLink);
+            
+            preg_match($searchPattern ,substr($proofLink,3),$success, PREG_OFFSET_CAPTURE,3); 
+            if($success === "Pingback" | "pingback"){
+                preg_match_all("/( (http|https):\/\/[^\s]*)/",$proofLink,$output); 
+                $this->setTargetLink($output); 
+                
+                        
+                }  elseif($this->htmlHeader($targetLink)) {
+                   
+                    $this->setTargetLink($this->htmlHeader($targetLink));  
+                    
+                    
+                    
+                }else{
+                    $o_flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
+                             't3lib_FlashMessage', ' Kein Pingback vorhanden ', \TYPO3\CMS\Core\Messaging\FlashMessage::OK
+                            );
+                            \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($o_flashMessage);
+                }            
+}
+
+         /**
+         * 
+         * @param type $sourceLink
+         * @param type $targetLink
+         */
+        
+         public function sendRequest($targetLink) {
+           
+            $ch = curl_init(); 
+            curl_setopt($ch, CURLOPT_URL, $targetLink); 
+            curl_setopt($ch, CURLOPT_HEADERFUNCTION, "callback");
+            $page = curl_exec($ch);    
+        }
+        
+        
+        /**
+         * 
+         * @param type $website
+         * @return string
+          */
+            
+          public function htmlHeader($website) {
+         
+            $response= file_get_contents($website, TRUE, NULL, 0, 5000); 
+            preg_match_all("/(link[^>].*pingback.*href=\")(.*)(\".*>)/iU",$response,$treffer); 
+                   
+            if(!isset($treffer[1][0])){
+                $treffer[1][0] =""; 
+            }else { 
+                
+                return $treffer[2][0]; 
+            }
+        }
+        
+        
+}
+?>
\ No newline at end of file
diff --git a/Configuration/ExtensionBuilder/settings.yaml b/Configuration/ExtensionBuilder/settings.yaml
new file mode 100644 (file)
index 0000000..ccb3496
--- /dev/null
@@ -0,0 +1,93 @@
+#
+# Extension Builder settings for extension pongback
+# generated 2014-01-29
+#
+# See http://www.yaml.org/spec/1.2/spec.html
+#
+
+---
+
+###########    Overwrite settings  ###########
+#
+# These settings only apply, if the roundtrip feature of the extension builder
+# is enabled in the extension manager
+#
+# Usage:
+# nesting reflects the file structure
+# a setting applies to a file or recursive to all files and subfolders
+#
+# merge:
+# means for classes: All properties ,methods and method bodies
+# of the existing class will be modified according to the new settings
+# but not overwritten
+#
+# for locallang xml files: Existing keys and labels are always
+# preserved (renaming in the GUI has only influence on the property and method names)
+#
+# for other files: You will find a Split token at the end of the file
+# After this token you can write whatever you want and it will be appended
+# everytime the code is generated
+#
+# keep:
+# files are never overwritten
+# These settings may break the functionality of the extension builder!
+# Handle with care!
+#
+#
+
+############  extension settings  ##############
+
+overwriteSettings:
+  Classes:
+    Controller: merge
+    Domain:
+      Model: merge
+      Repository: merge
+
+  Configuration:
+    #TCA: merge
+    #TypoScript: keep
+
+  Resources:
+    Private:
+      Language:
+        #locallang.xml: merge
+        #locallang.xlf: merge
+      #Templates: keep
+
+  ext_icon.gif: keep
+
+#  ext_localconf.php: merge
+
+#  ext_tables.php: merge
+
+#  ext_tables.sql: merge
+
+## ext_autoload.php is only needed in special cases ##
+createAutoloadRegistry: false
+
+######### settings for classBuilder #############################
+#
+# here you may define default parent classes for your classes
+# these settings only apply for new generated classes
+# you may also just change the parent class in the generated class file.
+# It will be kept on next code generation, if the overwrite settings
+# are configured to merge it
+#
+#  Experimental!!
+#################################################################
+
+classBuilder:
+
+  Controller:
+    parentClass: \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
+
+  Model:
+    AbstractEntity:
+      parentClass: \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
+
+    AbstractValueObject:
+      parentClass: \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject
+
+  Repository:
+    parentClass: \TYPO3\CMS\Extbase\Persistence\Repository
\ No newline at end of file
diff --git a/Configuration/TCA/Pingback.php b/Configuration/TCA/Pingback.php
new file mode 100644 (file)
index 0000000..730d7e6
--- /dev/null
@@ -0,0 +1,144 @@
+<?php
+if (!defined ('TYPO3_MODE')) {
+       die ('Access denied.');
+}
+
+$TCA['tx_pongback_domain_model_pingback'] = array(
+       'ctrl' => $TCA['tx_pongback_domain_model_pingback']['ctrl'],
+       'interface' => array(
+               'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, source_link, ping_client, ping_ressource, target_link, serialized_information',
+       ),
+       'types' => array(
+               '1' => array('showitem' => 'sys_language_uid;;;;1-1-1, l10n_parent, l10n_diffsource, hidden;;1, source_link, ping_client, ping_ressource, target_link, serialized_information,--div--;LLL:EXT:cms/locallang_ttc.xlf:tabs.access,starttime, endtime'),
+       ),
+       'palettes' => array(
+               '1' => array('showitem' => ''),
+       ),
+       'columns' => array(
+               'sys_language_uid' => array(
+                       'exclude' => 1,
+                       'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.language',
+                       'config' => array(
+                               'type' => 'select',
+                               'foreign_table' => 'sys_language',
+                               'foreign_table_where' => 'ORDER BY sys_language.title',
+                               'items' => array(
+                                       array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1),
+                                       array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0)
+                               ),
+                       ),
+               ),
+               'l10n_parent' => array(
+                       'displayCond' => 'FIELD:sys_language_uid:>:0',
+                       'exclude' => 1,
+                       'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.l18n_parent',
+                       'config' => array(
+                               'type' => 'select',
+                               'items' => array(
+                                       array('', 0),
+                               ),
+                               'foreign_table' => 'tx_pongback_domain_model_pingback',
+                               'foreign_table_where' => 'AND tx_pongback_domain_model_pingback.pid=###CURRENT_PID### AND tx_pongback_domain_model_pingback.sys_language_uid IN (-1,0)',
+                       ),
+               ),
+               'l10n_diffsource' => array(
+                       'config' => array(
+                               'type' => 'passthrough',
+                       ),
+               ),
+               't3ver_label' => array(
+                       'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.versionLabel',
+                       'config' => array(
+                               'type' => 'input',
+                               'size' => 30,
+                               'max' => 255,
+                       )
+               ),
+               'hidden' => array(
+                       'exclude' => 1,
+                       'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.hidden',
+                       'config' => array(
+                               'type' => 'check',
+                       ),
+               ),
+               'starttime' => array(
+                       'exclude' => 1,
+                       'l10n_mode' => 'mergeIfNotBlank',
+                       'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.starttime',
+                       'config' => array(
+                               'type' => 'input',
+                               'size' => 13,
+                               'max' => 20,
+                               'eval' => 'datetime',
+                               'checkbox' => 0,
+                               'default' => 0,
+                               'range' => array(
+                                       'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
+                               ),
+                       ),
+               ),
+               'endtime' => array(
+                       'exclude' => 1,
+                       'l10n_mode' => 'mergeIfNotBlank',
+                       'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.endtime',
+                       'config' => array(
+                               'type' => 'input',
+                               'size' => 13,
+                               'max' => 20,
+                               'eval' => 'datetime',
+                               'checkbox' => 0,
+                               'default' => 0,
+                               'range' => array(
+                                       'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
+                               ),
+                       ),
+               ),
+               'source_link' => array(
+                       'exclude' => 0,
+                       'label' => 'LLL:EXT:pongback/Resources/Private/Language/locallang_db.xlf:tx_pongback_domain_model_pingback.source_link',
+                       'config' => array(
+                               'type' => 'input',
+                               'size' => 30,
+                               'eval' => 'trim,required'
+                       ),
+               ),
+               'ping_client' => array(
+                       'exclude' => 0,
+                       'label' => 'LLL:EXT:pongback/Resources/Private/Language/locallang_db.xlf:tx_pongback_domain_model_pingback.ping_client',
+                       'config' => array(
+                               'type' => 'input',
+                               'size' => 30,
+                               'eval' => 'trim'
+                       ),
+               ),
+               'ping_ressource' => array(
+                       'exclude' => 1,
+                       'label' => 'LLL:EXT:pongback/Resources/Private/Language/locallang_db.xlf:tx_pongback_domain_model_pingback.ping_ressource',
+                       'config' => array(
+                               'type' => 'input',
+                               'size' => 30,
+                               'eval' => 'trim,required'
+                       ),
+               ),
+               'target_link' => array(
+                       'exclude' => 1,
+                       'label' => 'LLL:EXT:pongback/Resources/Private/Language/locallang_db.xlf:tx_pongback_domain_model_pingback.target_link',
+                       'config' => array(
+                               'type' => 'input',
+                               'size' => 30,
+                               'eval' => 'trim,required'
+                       ),
+               ),
+               'serialized_information' => array(
+                       'exclude' => 1,
+                       'label' => 'LLL:EXT:pongback/Resources/Private/Language/locallang_db.xlf:tx_pongback_domain_model_pingback.serialized_information',
+                       'config' => array(
+                               'type' => 'input',
+                               'size' => 30,
+                               'eval' => 'trim,required'
+                       ),
+               ),
+       ),
+);
+
+?>
\ No newline at end of file
diff --git a/Configuration/TypoScript/base.setup.ts b/Configuration/TypoScript/base.setup.ts
new file mode 100644 (file)
index 0000000..468501f
--- /dev/null
@@ -0,0 +1,80 @@
+###########################################
+# Language Setup                          #
+###########################################
+
+# Anzeige Default-Sprache im Backend als Deutsch festlegen
+mod.SHARED {
+   defaultLanguageFlag = de
+   defaultLanguageLabel = Deutsch
+}
+
+[globalVar=GP:L=1]
+    config.sys_language_uid = 1
+    config.language = en
+    config.locale_all = en_EN
+    htmlTag_langKey = en
+[global]
+
+sys_language_mode = content_fallback
+    sys_language_overlay = hideNonTranslated
+    sys_language_uid = 0 
+    language = de
+    locale_all = de_DE
+##Für English dann die globale variabel ausserhalb der Config
+
+[globalVar=GP:L=1]
+    config.sys_language_uid = 1
+    config.language = en
+    config.locale_all = en_EN
+    htmlTag_langKey = en
+[global]
+###zum umstellen der sprache habe ich dann in einem typoscript
+
+[globalVar = GP:L = 1]
+    lib.menu.20.value=<div id="Opening"><h4>Opening</h4><span class="opening">Monday to Saturday<br />From 12 to 22 o'clock</span></div>
+[global]
+
+##der text darin ist jetzt nur für ein Asia Restaurant gewesen^^
+##er ändert quasi lib.menu.20.value wenn  die globalVar = GP: L = 1
+##Hab hier noch ein language menu
+
+ 20 = HMENU
+        20 {
+            # Ein Sprach-Menü wird erzeugt
+            special = language
+            # Reihenfolge und Auswahl der Sprachen im Menü
+            special.value = 1,0
+            special.normalWhenNoLanguage = 0
+            wrap =<ul id="LanguageNavigation">|</ul>
+            1 = TMENU
+            1 {
+                noBlur = 1
+                # Standard Sprachen
+                NO = 1
+                NO {
+                    linkWrap =<li class="firstLevel">|</li>
+                    # Standard-Titel für den Link wäre Seitenttitel
+                    # =&gt; anderer Text als Link-Text (Optionsschift)
+                    stdWrap.override = english || deutsch 
+                    # Standardmäßige Verlinkung des Menüs ausschalten
+                    # Da diese sonstige GET-Parameter nicht enthält
+                    doNotLinkIt = 1
+                    # Nun wird der Link mit den aktuellen GET-Parametern neu aufgebaut
+                    stdWrap.typolink.parameter.data = page:uid
+                    stdWrap.typolink.additionalParams = &L=1 || &L=0
+                    stdWrap.typolink.addQueryString = 1
+                    stdWrap.typolink.addQueryString.exclude = L,id,cHash,no_cache
+                    stdWrap.typolink.addQueryString.method = GET
+                    stdWrap.typolink.useCacheHash = 1
+                    stdWrap.typolink.no_cache = 0
+
+                }
+                # Aktive Sprache
+                ACT <.NO
+                ACT.linkWrap =<li class="firstLevel act">|</li>
+                # NO + Übersetzung nicht vorhanden
+                USERDEF1 <.NO
+                # ACT + Übersetzung nicht vorhanden
+                USERDEF2 < .ACT
+            }
+        }
\ No newline at end of file
diff --git a/Configuration/TypoScript/constants.txt b/Configuration/TypoScript/constants.txt
new file mode 100644 (file)
index 0000000..ede071f
--- /dev/null
@@ -0,0 +1,29 @@
+plugin.tx_pongback {
+       view {
+               # cat=plugin.tx_pongback/file; type=string; label=Path to template root (FE)
+               templateRootPath = EXT:pongback/Resources/Private/Templates/
+               # cat=plugin.tx_pongback/file; type=string; label=Path to template partials (FE)
+               partialRootPath = EXT:pongback/Resources/Private/Partials/
+               # cat=plugin.tx_pongback/file; type=string; label=Path to template layouts (FE)
+               layoutRootPath = EXT:pongback/Resources/Private/Layouts/
+       }
+       persistence {
+               # cat=plugin.tx_pongback//a; type=string; label=Default storage PID
+               storagePid = 0
+       }
+}
+
+module.tx_pongback {
+       view {
+               # cat=module.tx_pongback/file; type=string; label=Path to template root (BE)
+               templateRootPath = EXT:pongback/Resources/Private/Backend/Templates/
+               # cat=module.tx_pongback/file; type=string; label=Path to template partials (BE)
+               partialRootPath = EXT:pongback/Resources/Private/Backend/Partials/
+               # cat=module.tx_pongback/file; type=string; label=Path to template layouts (BE)
+               layoutRootPath = EXT:pongback/Resources/Private/Backend/Layouts/
+       }
+       persistence {
+               # cat=module.tx_pongback//a; type=string; label=Default storage PID
+               storagePid = 
+       }
+}
\ No newline at end of file
diff --git a/Configuration/TypoScript/setup.txt b/Configuration/TypoScript/setup.txt
new file mode 100644 (file)
index 0000000..9834a1d
--- /dev/null
@@ -0,0 +1,54 @@
+plugin.tx_pongback {
+       view {
+               templateRootPath = {$plugin.tx_pongback.view.templateRootPath}
+               partialRootPath = {$plugin.tx_pongback.view.partialRootPath}
+               layoutRootPath = {$plugin.tx_pongback.view.layoutRootPath}
+       }
+       persistence {
+               storagePid = {$plugin.tx_pongback.persistence.storagePid}
+                   # Pingbacks werden da gespeichert auf der sie eingehen 
+       }
+       features {
+               # uncomment the following line to enable the new Property Mapper.
+               # rewrittenPropertyMapper = 1
+       }
+}
+
+ # Module configuration
+module.tx_pongback {
+       persistence {
+               storagePid = {$module.tx_pongback.persistence.storagePid}
+       }
+       view {
+               templateRootPath = {$module.tx_pongback.view.templateRootPath}
+               partialRootPath = {$module.tx_pongback.view.partialRootPath}
+               layoutRootPath = {$module.tx_pongback.view.layoutRootPath}
+       }
+}
+
+page.headerData.1392814115 = TEXT
+page.headerData.1392814115 {
+    value = pingback
+    typolink.parameter = 1
+    typolink.additionalParams = &type=1392814100
+    typolink.returnLast = url
+    typolink.forceAbsoluteUrl = 1
+    wrap = <link rel="pingback" href="|">
+}
+
+
+PingbackEndpoint = PAGE
+PingbackEndpoint {
+    typeNum = 1392814100
+    config {
+        disableAllHeaderCode = 1
+        xhtml_cleaning = 0
+        admPanel = 0
+        debug = 0
+        no_cache = 1
+        additionalHeaders = Content-Type:text/xml
+    }
+    10 < tt_content.list.20.pongback_server
+}
+
+page.includeCSS.pongback = EXT:pongback/Resources/Public/Styles/PongbackStyle.css
diff --git a/ExtensionBuilder.json b/ExtensionBuilder.json
new file mode 100644 (file)
index 0000000..424d0cd
--- /dev/null
@@ -0,0 +1 @@
+{"modules":[{"config":{"position":[347,27]},"name":"New Model Object","value":{"actionGroup":{"_default0_list":true,"_default1_show":true,"_default2_new_create":false,"_default3_edit_update":false,"_default4_delete":false,"customActions":[]},"name":"Pingback","objectsettings":{"aggregateRoot":true,"description":"","mapToTable":"","parentClass":"","sorting":true,"type":"Entity","uid":"98036017855"},"propertyGroup":{"properties":[{"propertyDescription":"","propertyIsExcludeField":false,"propertyIsRequired":true,"propertyName":"sourceLink","propertyType":"String","uid":"1248912950766"},{"propertyDescription":"","propertyIsExcludeField":false,"propertyIsRequired":false,"propertyName":"pingClient","propertyType":"String","uid":"851837798234"},{"propertyDescription":"","propertyIsExcludeField":true,"propertyIsRequired":true,"propertyName":"pingRessource","propertyType":"String","uid":"827678032238"},{"propertyDescription":"","propertyIsExcludeField":true,"propertyIsRequired":true,"propertyName":"targetLink","propertyType":"String","uid":"942036569585"},{"propertyDescription":"","propertyIsExcludeField":true,"propertyIsRequired":true,"propertyName":"serializedInformation","propertyType":"String","uid":"427294720885"}]},"relationGroup":{"relations":[]}}}],"properties":{"backendModules":[{"actions":{"controllerActionCombinations":""},"description":"administrationView","key":"pongbackBackend","mainModule":"web","name":"Pongback","tabLabel":"Pingback Administration "}],"description":"Senden und Empfangen eines Pingbacks","emConf":{"category":"plugin","custom_category":"","dependsOn":"extbase => 6.0\nfluid => 6.0\ntypo3 => 6.0\n","disableVersioning":false,"priority":"","shy":false,"state":"alpha","targetVersion":"6.0","version":"0.1"},"extensionKey":"pongback","name":"Pongback","originalExtensionKey":"pongback","persons":[{"company":"PHTH","email":"michael.blunck@phth.de","name":"Michael Blunck","role":"Developer"}],"plugins":[{"actions":{"controllerActionCombinations":"","noncacheableActions":"","switchableActions":""},"key":"pongbackFrontend","name":"Pongback"}],"vendorName":"PHTH"},"wires":[],"log":{"last_modified":"2014-02-12 08:24","extension_builder_version":"2.5.2","be_user":" (1)"}}
\ No newline at end of file
diff --git a/Readme.rst b/Readme.rst
new file mode 100644 (file)
index 0000000..c2f1f2b
--- /dev/null
@@ -0,0 +1,15 @@
+Extension Manual
+=================
+
+This is a template manual aiming to pave the way to developers when it comes about documentation. The template provides a structure that a developer can take over and, in addition, many useful snippets and examples. Documentation is written in reST format. Refer to Help writing reStructuredText to get some more insight about the syntax and available reST editors. For instance, you might be particularly interested how you can :
+
+* generate the documentation using on-line services (@todo to write) 
+* `make links`_ accros projects
+* how you should write TypoScript reference.
+
+Any idea or suggestion for improving this template `can be drop`_ to our team_. And remember: documentation is like gift wrapping, it looks like superfluous, but your friend tends to be rather disappointed when their presents arrive in supermarket carrier bags. (Documentation-Driven Design quote)
+
+.. _can be drop: http://forge.typo3.org/projects/typo3v4-official_extension_template/issues
+.. _team: http://forge.typo3.org/projects/typo3v4-official_extension_template
+.. _make links: RestructuredtextHelp.html#cross-linking
+.. _can write TypoScript: RestructuredtextHelp.html#typoscript-reference
diff --git a/Resources/Private/.htaccess b/Resources/Private/.htaccess
new file mode 100644 (file)
index 0000000..dfc0272
--- /dev/null
@@ -0,0 +1 @@
+deny  from all
\ No newline at end of file
diff --git a/Resources/Private/Backend/Layouts/Default.html b/Resources/Private/Backend/Layouts/Default.html
new file mode 100644 (file)
index 0000000..38e5bb2
--- /dev/null
@@ -0,0 +1,34 @@
+<f:be.container>
+       <div class="typo3-fullDoc">
+               <div id="typo3-docheader">
+                       <div id="typo3-docheader-row1">
+                               <div class="buttonsleft">
+
+                               </div>
+                               <div class="buttonsright">
+                                       <f:be.buttons.shortcut />
+                               </div>
+                       </div>
+                       <div id="typo3-docheader-row2">
+                               <!--<div class="docheader-row2-left">
+                                       <f:be.buttons.csh />
+                                       <f:be.menus.actionMenu>
+                                               <f:be.menus.actionMenuItem label="Overview" controller="" action="list" />
+                                               <f:be.menus.actionMenuItem label="Create new Pingback" action="new" controller="Pingback" />
+                                       </f:be.menus.actionMenu>
+                               </div>-->
+                               <div class="docheader-row2-right">
+                                       <f:be.pagePath />
+                                       <f:be.pageInfo />
+                               </div>
+                       </div>
+
+               </div>
+               <div id="typo3-docbody">
+                       <div id="typo3-inner-docbody">
+                               <f:flashMessages renderMode="div" />
+                               <f:render section="content" />
+                       </div>
+               </div>
+       </div>
+</f:be.container>
\ No newline at end of file
diff --git a/Resources/Private/Backend/Partials/Pingback/Properties.html b/Resources/Private/Backend/Partials/Pingback/Properties.html
new file mode 100644 (file)
index 0000000..6cfa734
--- /dev/null
@@ -0,0 +1,42 @@
+<table class="tx-pongback" >
+       <tr>
+               <td>
+                       <f:translate key="tx_pongback_domain_model_pingback.source_link" />
+               </td>
+               <td>
+                       {pingback.sourceLink}
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       <f:translate key="tx_pongback_domain_model_pingback.ping_client" />
+               </td>
+               <td>
+                       {pingback.pingClient}
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       <f:translate key="tx_pongback_domain_model_pingback.ping_ressource" />
+               </td>
+               <td>
+                       {pingback.pingRessource}
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       <f:translate key="tx_pongback_domain_model_pingback.target_link" />
+               </td>
+               <td>
+                       {pingback.targetLink}
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       <f:translate key="tx_pongback_domain_model_pingback.serialized_information" />
+               </td>
+               <td>
+                       {pingback.serializedInformation}
+               </td>
+       </tr>
+</table>
\ No newline at end of file
diff --git a/Resources/Private/Backend/Templates/Pingback/Administer.html b/Resources/Private/Backend/Templates/Pingback/Administer.html
new file mode 100644 (file)
index 0000000..ef873c0
--- /dev/null
@@ -0,0 +1,43 @@
+<f:layout name="Default" />
+
+<f:section name="content">
+    <h1><th><f:translate key="tx_pongback_domain_model_pingback.headline_backend" /></th></h1>
+
+<f:flashMessages />
+<div id="pongbackBackend">
+<table border="1" frame="void" width="80%" align="center" class="tx_pongback" >
+       
+    <tr>
+               <th><f:translate key="tx_pongback_domain_model_pingback.source_link" /></th>
+                <th><f:translate key="tx_pongback_domain_model_pingback.target_link" /></th>
+               <!--<th><f:translate key="tx_pongback_domain_model_pingback.ping_client" /></th>
+               <th><f:translate key="tx_pongback_domain_model_pingback.ping_ressource" /></th>-->
+               <th><f:translate key="tx_pongback_domain_model_pingback.serialized_information" /></th>
+               <!-- <th>hidden</th><f:translate key="tx_pongback_domain_model_pingback.serialized_information" />-->
+               <th><f:translate key="tx_pongback_domain_model_pingback.pingback_column_publish_heading"  /></th>
+                <th><f:translate key="tx_pongback_domain_model_pingback.pingback_column_delete_heading" /></th>
+                </tr>
+
+       <f:for each="{pingbacks}" as="pingback">
+               <tr>
+                       <td><f:link.external uri="{pingback.sourceLink}" target="_blank"> {pingback.sourceLink}</f:link.external></td>
+                       <td><f:link.external uri="{pingback.targetLink}" target="_blank"> {pingback.targetLink}</f:link.external></td>
+                       <td><f:link.external uri="{pingback.sourceLink}" target="_blank"> {pingback.serializedInformation}</f:link.external></td>
+                         <!-- <td><f:link.action action="show" arguments="{pingback : pingback}"> {pingback.colums}</f:link.action></td>-->
+                       <f:if condition="{pingback.hidden}">
+                            <f:then>
+                                <td><f:link.action action="publish" arguments="{pingback : pingback}"><f:translate key="tx_pongback_domain_model_pingback.pingback_publish" /></f:link.action></td>
+                            </f:then>
+                            <f:else>
+                                <td><f:link.action action="unpublish" arguments="{pingback : pingback.uid}"><f:translate key="tx_pongback_domain_model_pingback.pingback_unpublish" /></f:link.action></td>
+                            </f:else>
+                        </f:if>
+                        
+                        
+                       <td><f:link.action action="delete" arguments="{pingback : pingback}"><f:translate key="tx_pongback_domain_model_pingback.pingback_delete"  /></f:link.action></td>
+               </tr>
+       </f:for>
+</table>
+</div>
+<!--<f:link.action action="new">New Pingback</f:link.action>--> 
+</f:section>
\ No newline at end of file
diff --git a/Resources/Private/Backend/Templates/Pingback/Show.html b/Resources/Private/Backend/Templates/Pingback/Show.html
new file mode 100644 (file)
index 0000000..6a7e236
--- /dev/null
@@ -0,0 +1,21 @@
+<f:layout name="Default" />
+
+This Template is responsible for displaying a single view for a domain object
+
+If you modify this template, do not forget to change the overwrite settings
+in /Configuration/ExtensionBuilder/settings.yaml:
+  Resources:
+    Private:
+      Templates:
+        Show.html: keep
+
+Otherwise your changes will be overwritten the next time you save the extension in the extension builder
+
+<f:section name="content">
+<h1>Single View for Pingback</h1>
+
+<f:flashMessages />
+<f:render partial="Pingback/Properties" arguments="{pingback:pingback}" />
+<f:link.action action="list">Back to list</f:link.action><br />
+<!--<f:link.action action="create">New Pingback</f:link.action>-->
+</f:section>
\ No newline at end of file
diff --git a/Resources/Private/Language/de_locallang.xlf b/Resources/Private/Language/de_locallang.xlf
new file mode 100644 (file)
index 0000000..ddf32b3
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<xliff version="1.0">
+       <file source-language="de" datatype="plaintext" original="messages" date="2014-02-12T08:24:48Z" product-name="pongback">
+               <header/>
+                
+               <body>
+                    <trans-unit id="tx_pongback_domain_model_pingback.error_targetlink">
+                               <source>Pingbackübereinstimmung gescheitert</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback">
+                               <source>Pingback</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.source_link">
+                               <source>Quelllink</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.ping_client">
+                               <source></source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.ping_ressource">
+                               <source>Inhalt</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.target_link">
+                               <source>Ziellink</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.serialized_information">
+                               <source>Information</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.pingback_arrived_alert_mail">
+                               <source>soeben ein ein neuer Pingback eingetroffen von </source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.pingback_arrived_alert_mail_subject">
+                               <source>Ein neuer Pingback ist eingetroffen</source>
+                       </trans-unit>
+                         <trans-unit id="tx_pongback_domain_model_pingback.pingback_publish">
+                               <source>veröffentlicht</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.pingback_unpublish">
+                               <source>unveröffentlicht</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.pingback_column_publish_heading">
+                               <source>Veröffentlichen</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.pingback_column_delete_heading">
+                               <source>Löschen</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.headline_backend">
+                               <source>Empfangene Pingbacks</source>
+                       </trans-unit>
+                        
+                </body>
+       </file>
+</xliff>
\ No newline at end of file
diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf
new file mode 100644 (file)
index 0000000..41978a7
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<xliff version="1.0">
+       <file source-language="en" datatype="plaintext" original="messages" date="2014-02-12T08:24:48Z" product-name="pongback">
+               <header/>
+               <body>
+                        <trans-unit id="xmlrpc.pingback.ping.success">
+                               <source>Success</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback">
+                               <source>Pingback</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.source_link">
+                               <source>Source Link</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.ping_client">
+                               <source>Ping Client</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.ping_ressource">
+                               <source>Ressource</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.target_link">
+                               <source>Target Link</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.serialized_information">
+                               <source>Serialized Information</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.error_targetlink">
+                               <source>Pingback agreement failure</source>
+                       </trans-unit>
+                         <trans-unit id="tx_pongback_domain_model_pingback.error_noInformations">
+                               <source>Link not found</source>
+                       </trans-unit>
+                           <trans-unit id="tx_pongback_domain_model_pingback.pingback_arrived_alert_mail">
+                               <source>Pingback arrived from</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.pingback_arrived_alert_mail_subject">
+                               <source>Pingback Alert</source>
+                       </trans-unit>
+                       <trans-unit id="tcemain.pingback.ping.refused">
+                               <source>The Pingback was refused from %s for the following reason: %s.</source>
+                       </trans-unit>
+                        <trans-unit id="tcemain.pingback.ping.accepted">
+                               <source>Pingback accepted from %s.</source>
+                       </trans-unit>
+                        <trans-unit id="tcemain.pingback.ping.not_sent">
+                               <source>Pingback was not sent because of the tt_content or page is hidden.</source>
+                       </trans-unit>
+                        <trans-unit id="tcemain.pingback.ping.not_sent_title">
+                               <source>Pingback not sent</source>
+                       </trans-unit>
+                        <trans-unit id="tcemain.pingback.ping.accepted_title">
+                               <source>Pingback accepted</source>
+                       </trans-unit>
+                        <trans-unit id="tcemain.pingback.ping.refused_title">
+                               <source>Pingback refused</source>
+                       </trans-unit>
+                         <trans-unit id="tx_pongback_domain_model_pingback.pingback_publish">
+                               <source>Publish</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.pingback_unpublish">
+                               <source>Unpublish</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.pingback_column_publish_heading">
+                               <source>Release</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.pingback_column_delete_heading">
+                               <source>Delete</source>
+                       </trans-unit>
+                         <trans-unit id="tx_pongback_domain_model_pingback.pingback_delete">
+                               <source>Delete</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.headline_backend">
+                               <source>Received Pingbacks</source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
\ No newline at end of file
diff --git a/Resources/Private/Language/locallang_csh_tx_pongback_domain_model_pingback.xlf b/Resources/Private/Language/locallang_csh_tx_pongback_domain_model_pingback.xlf
new file mode 100644 (file)
index 0000000..73ebc2d
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<xliff version="1.0">
+       <file source-language="en" datatype="plaintext" original="messages" date="2014-02-12T08:24:48Z" product-name="pongback">
+               <header/>
+               <body>
+
+                       <trans-unit id="source_link.description">
+                               <source>Source Link</source>
+                       </trans-unit>
+                       <trans-unit id="ping_client.description">
+                               <source>Ping Client</source>
+                       </trans-unit>
+                       <trans-unit id="ping_ressource.description">
+                               <source>Ressource</source>
+                       </trans-unit>
+                       <trans-unit id="target_link.description">
+                               <source>Target Link</source>
+                       </trans-unit>
+                       <trans-unit id="serialized_information.description">
+                               <source>Serialized Information</source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
\ No newline at end of file
diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf
new file mode 100644 (file)
index 0000000..857882a
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<xliff version="1.0">
+       <file source-language="en" datatype="plaintext" original="messages" date="2014-02-12T08:24:48Z" product-name="pongback">
+               <header/>
+               <body>
+
+                       <trans-unit id="tx_pongback_domain_model_pingback">
+                               <source>Pingback</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.source_link">
+                               <source>Source Link</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.ping_client">
+                               <source>Ping Client</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.ping_ressource">
+                               <source>Ping Ressource</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.target_link">
+                               <source>Target Link</source>
+                       </trans-unit>
+                       <trans-unit id="tx_pongback_domain_model_pingback.serialized_information">
+                               <source>Serialized Information</source>
+                       </trans-unit>
+                        <trans-unit id="tx_pongback_domain_model_pingback.error_targetlink">
+                               <source>Pingback agreement failure</source>
+                       </trans-unit>
+
+               </body>
+       </file>
+</xliff>
+
diff --git a/Resources/Private/Language/locallang_pongbackbackend.xlf b/Resources/Private/Language/locallang_pongbackbackend.xlf
new file mode 100644 (file)
index 0000000..25e7a2a
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<xliff version="1.0">
+       <file source-language="en" datatype="plaintext" original="messages" date="2014-02-12T08:24:48Z" product-name="pongback">
+               <header/>
+               <body>
+                       
+            <trans-unit id="mlang_tabs_tab">
+                               <source>Pongback</source>
+                       </trans-unit>
+                       <trans-unit id="mlang_labels_tabdescr">
+                               <source>Administration View</source>
+                       </trans-unit>
+                       <trans-unit id="mlang_labels_tablabel">
+                               <source>Pingback Administration </source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
\ No newline at end of file
diff --git a/Resources/Private/Layouts/Default.html b/Resources/Private/Layouts/Default.html
new file mode 100644 (file)
index 0000000..9b52a60
--- /dev/null
@@ -0,0 +1,3 @@
+<div class="tx-pongback">
+       <f:render section="main" />
+</div>
\ No newline at end of file
diff --git a/Resources/Private/Partials/Pingback/Properties.html b/Resources/Private/Partials/Pingback/Properties.html
new file mode 100644 (file)
index 0000000..6cfa734
--- /dev/null
@@ -0,0 +1,42 @@
+<table class="tx-pongback" >
+       <tr>
+               <td>
+                       <f:translate key="tx_pongback_domain_model_pingback.source_link" />
+               </td>
+               <td>
+                       {pingback.sourceLink}
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       <f:translate key="tx_pongback_domain_model_pingback.ping_client" />
+               </td>
+               <td>
+                       {pingback.pingClient}
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       <f:translate key="tx_pongback_domain_model_pingback.ping_ressource" />
+               </td>
+               <td>
+                       {pingback.pingRessource}
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       <f:translate key="tx_pongback_domain_model_pingback.target_link" />
+               </td>
+               <td>
+                       {pingback.targetLink}
+               </td>
+       </tr>
+       <tr>
+               <td>
+                       <f:translate key="tx_pongback_domain_model_pingback.serialized_information" />
+               </td>
+               <td>
+                       {pingback.serializedInformation}
+               </td>
+       </tr>
+</table>
\ No newline at end of file
diff --git a/Resources/Private/Templates/Pingback/List.html b/Resources/Private/Templates/Pingback/List.html
new file mode 100644 (file)
index 0000000..214b614
--- /dev/null
@@ -0,0 +1,37 @@
+<f:layout name="Default" />
+
+This Template is responsible for creating a table of domain objects.
+
+If you modify this template, do not forget to change the overwrite settings
+in /Configuration/ExtensionBuilder/settings.yaml:
+  Resources:
+    Private:
+      Templates:
+        List.html: keep
+
+Otherwise your changes will be overwritten the next time you save the extension in the extension builder
+<!--Frontend shows only this what the user want-->
+<f:section name="main">
+<div class="tx_pongback_text">Pingbacks</div>
+
+<f:flashMessages />
+<div id="pongbackFrontend">
+    <table class="tx_pongback" >
+        <tr>
+
+        <th><f:translate key="tx_pongback_domain_model_pingback.source_link" /></th>
+        <th><f:translate key="tx_pongback_domain_model_pingback.target_link" /></th>
+        <th><f:translate key="tx_pongback_domain_model_pingback.serialized_information" /></th>
+        </tr>
+
+        <f:for each="{pingbacks}" as="pingback">
+            <tr>
+            <td> <f:link.external uri="{pingback.sourceLink}" target="_blank">{pingback.sourceLink}</f:link.external></td>
+            <td><f:link.external uri="{pingback.targetLink}" target="_blank"> {pingback.targetLink}</f:link.external></td>
+            <td> <f:link.external uri="{pingback.sourceLink}" target="_blank">{pingback.serializedInformation}</f:link.external></td>
+
+        </f:for>
+    </table>
+</div>
+
+</f:section>
\ No newline at end of file
diff --git a/Resources/Private/Templates/Pingback/Show.html b/Resources/Private/Templates/Pingback/Show.html
new file mode 100644 (file)
index 0000000..3253a3e
--- /dev/null
@@ -0,0 +1,29 @@
+<f:layout name="Default" />
+
+This Template is responsible for displaying a single view for a domain object
+
+If you modify this template, do not forget to change the overwrite settings
+in /Configuration/ExtensionBuilder/settings.yaml:
+  Resources:
+    Private:
+      Templates:
+        Show.html: keep
+
+Otherwise your changes will be overwritten the next time you save the extension in the extension builder
+
+<f:section name="main">
+<h1>Single View for Pingback</h1>
+
+<f:flashMessages />
+<f:render partial="Pingback/Properties" arguments="{pingback:pingback}" />
+          <f:for each="{pingbacks}" as="pingback">
+              <table class="tx_pongback" >
+              <tr>
+            <td> {pingback.sourceLink}</td>
+            <td> {pingback.targetLink}</td>
+            <td> {pingback.serializedInformation}</td>
+            </table>
+        </f:for>
+<f:link.action action="list">Back to list</f:link.action><br />
+<f:link.action action="new">New Pingback</f:link.action>
+</f:section>
\ No newline at end of file
diff --git a/Resources/Public/Icons/relation.gif b/Resources/Public/Icons/relation.gif
new file mode 100644 (file)
index 0000000..db61d7e
Binary files /dev/null and b/Resources/Public/Icons/relation.gif differ
diff --git a/Resources/Public/Icons/tx_pongback_domain_model_pingback.gif b/Resources/Public/Icons/tx_pongback_domain_model_pingback.gif
new file mode 100644 (file)
index 0000000..6cc5f16
Binary files /dev/null and b/Resources/Public/Icons/tx_pongback_domain_model_pingback.gif differ
diff --git a/Resources/Public/Styles/PongbackStyle.css b/Resources/Public/Styles/PongbackStyle.css
new file mode 100644 (file)
index 0000000..143f600
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/* 
+    Created on : 21.02.2014, 15:48:53
+    Author     : Michael
+*/
+.tx_pongback{
+        display: inline-block; 
+        font-family: cursive;
+     
+    
+}
+
+.tx_pongback_text{
+    
+    text-align: center; 
+    font-family: Arial; 
+    border-top-left-radius: 30px;
+    border-top-right-radius: 30px;
+    background-color: skyblue;
+    margin: auto 0 ; 
+    text-decoration: underline; 
+}
+
+#pongbackFrontend{
+        display: inline-table; 
+        margin: 0 auto; 
+        
+        font-family: cursive; 
+        background-image: -webkit-linear-gradient(skyblue 20%, #9FBFD2 80%); 
+        background-image: -moz-linear-gradient(skyblue 20%, #9FBFD2 80%); 
+        background-image: -o-linear-gradient(skyblue 20%, #9FBFD2 80%); 
+        background-image: linear-gradient(skyblue 20%, #9FBFD2 80%);; 
+        text-align: center;
+        
+        
+        text-decoration: none; 
+        box-shadow: 5px 5px 5px black; 
+        border-bottom-left-radius: 2px;
+        border-bottom-right-radius: 2px;
+     
+}
+
+#pongbackFrontend th{
+    
+    text-spacing: space-start; 
+    
+}
+
+#pongbackFrontend tr{
+     display: table-row-group; 
+    
+    
+}
+
+
+#pongbackFrontend td{
+    padding: 5px; 
+    
+}
+
+#pongbackBackend {
+    
+   display: inline-table; 
+        margin: 0 auto; 
+       
+        font-family: cursive; 
+        background-color: skyblue; 
+        text-align: center; 
+        
+        text-decoration: none; 
+        text-shadow: 1px black; 
+}
diff --git a/Tests/Unit/Controller/PingbackControllerTest.php b/Tests/Unit/Controller/PingbackControllerTest.php
new file mode 100644 (file)
index 0000000..513e7b4
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+namespace PHTH\Pongback\Tests;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2014 Michael Blunck <michael.blunck@phth.de>, PHTH
+ *                     
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Test case for class Tx_Pongback_Controller_PingbackController.
+ *
+ * @version $Id$
+ * @copyright Copyright belongs to the respective authors
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
+ *
+ * @package TYPO3
+ * @subpackage Pongback
+ *
+ * @author Michael Blunck <michael.blunck@phth.de>
+ */
+class PingbackControllerTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
+       /**
+        * @var 
+        */
+       protected $fixture;
+
+       public function setUp() {
+               $this->fixture = new \PHTH\Pongback\Domain\Model\Pingback();
+       }
+
+       public function tearDown() {
+               unset($this->fixture);
+       }
+
+       /**
+        * @test
+        */
+       public function dummyMethod() {
+               $this->markTestIncomplete();
+       }
+
+            
+              
+                
+                        
+                
+            
+      
+        
+}
+?>
\ No newline at end of file
diff --git a/Tests/Unit/Domain/Model/PingbackTest.php b/Tests/Unit/Domain/Model/PingbackTest.php
new file mode 100644 (file)
index 0000000..6213130
--- /dev/null
@@ -0,0 +1,157 @@
+<?php
+
+namespace PHTH\Pongback\Tests;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2014 Michael Blunck <michael.blunck@phth.de>, PHTH
+ *                     
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Test case for class \PHTH\Pongback\Domain\Model\Pingback.
+ *
+ * @version $Id$
+ * @copyright Copyright belongs to the respective authors
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
+ *
+ * @package TYPO3
+ * @subpackage Pongback
+ *
+ * @author Michael Blunck <michael.blunck@phth.de>
+ */
+class PingbackTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
+       /**
+        * @var \PHTH\Pongback\Domain\Model\Pingback
+        */
+       protected $fixture;
+
+       public function setUp() {
+               $this->fixture = new \PHTH\Pongback\Domain\Model\Pingback();
+       }
+
+       public function tearDown() {
+               unset($this->fixture);
+       }
+
+       /**
+        * @test
+        */
+       public function getSourceLinkReturnsInitialValueForString() { }
+
+       /**
+        * @test
+        */
+       public function setSourceLinkForStringSetsSourceLink() { 
+               $this->fixture->setSourceLink('Conceived at T3CON10');
+
+               $this->assertSame(
+                       'Conceived at T3CON10',
+                       $this->fixture->getSourceLink()
+               );
+       }
+       
+       /**
+        * @test
+        */
+       public function getPingClientReturnsInitialValueForString() { }
+
+       /**
+        * @test
+        */
+       public function setPingClientForStringSetsPingClient() { 
+               $this->fixture->setPingClient('Conceived at T3CON10');
+
+               $this->assertSame(
+                       'Conceived at T3CON10',
+                       $this->fixture->getPingClient()
+               );
+       }
+       
+       /**
+        * @test
+        */
+       public function getPingRessourceReturnsInitialValueForString() { }
+
+       /**
+        * @test
+        */
+       public function setPingRessourceForStringSetsPingRessource() { 
+               $this->fixture->setPingRessource('Conceived at T3CON10');
+
+               $this->assertSame(
+                       'Conceived at T3CON10',
+                       $this->fixture->getPingRessource()
+               );
+       }
+       
+       /**
+        * @test
+        */
+       public function getTargetLinkReturnsInitialValueForString() { }
+
+       /**
+        * @test
+        */
+       public function setTargetLinkForStringSetsTargetLink() { 
+               $this->fixture->setTargetLink('Conceived at T3CON10');
+
+               $this->assertSame(
+                       'Conceived at T3CON10',
+                       $this->fixture->getTargetLink()
+               );
+       }
+       
+       /**
+        * @test
+        */
+       public function getSerializedInformationReturnsInitialValueForString() { }
+
+       /**
+        * @test
+        */
+       public function setSerializedInformationForStringSetsSerializedInformation() { 
+               $this->fixture->setSerializedInformation('Conceived at T3CON10');
+
+               $this->assertSame(
+                       'Conceived at T3CON10',
+                       $this->fixture->getSerializedInformation()
+               );
+       }
+        /**
+        * @var PHTH\Pongback\Classes\Domain\Model\RequestPingback
+        * 
+        */
+       protected $checkURL; 
+       
+       /**
+        * @test
+        */
+       public function validURLForTheTargetLink() {
+                $url = "http://de1.php.net/manual-lookup.php?pattern=ping&scope=quickref"; 
+               $url2 =  "http://de1.php.net/manual-lookup.php?pattern=ping&scope=quickref" ; 
+               
+              $this->assertSame("URL",$this->checkURL->requestPingback($url, $url2)); 
+        }  
+        
+  
+       
+}
+?>
\ No newline at end of file
diff --git a/doc/Benutzerhandbuch.sxw b/doc/Benutzerhandbuch.sxw
new file mode 100644 (file)
index 0000000..65a9b35
Binary files /dev/null and b/doc/Benutzerhandbuch.sxw differ
diff --git a/doc/manual.sxw b/doc/manual.sxw
new file mode 100644 (file)
index 0000000..65a9b35
Binary files /dev/null and b/doc/manual.sxw differ
diff --git a/ext_autoload.php b/ext_autoload.php
new file mode 100644 (file)
index 0000000..50adbf0
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+$extensionPath = t3lib_extMgm::extPath('pongback');
+
+$libraryPath = $extensionPath.'Classes/Library/fXmlRpc/';
+
+$autoloadArray = array();
+/**
+ * This is why we must include the fXmlRpc libary 
+ * search all files and directories and include it 
+ */
+    $classes = \TYPO3\CMS\Core\Utility\GeneralUtility::getAllFilesAndFoldersInPath($autoloadArray, $libraryPath, 'php', $regDirs, 2);
+foreach($classes as $class) {
+    $alias = str_replace($libraryPath, 'fXmlRpc\\', $class);
+    $alias = str_replace('/', '\\', $alias);
+    $alias = str_replace('.php', '', $alias);
+    $autoloadArray[$alias] = $class;
+}
+return $autoloadArray;
+
+
+?>
\ No newline at end of file
diff --git a/ext_conf_template.txt b/ext_conf_template.txt
new file mode 100644 (file)
index 0000000..2c41175
--- /dev/null
@@ -0,0 +1,7 @@
+# cat=basic/enable; type=string; label=Notification Mail Address:Optional - If you placed an email addresss here, a notification mail will be generated on every incoming pingback
+notificationAddress = 
+
+# cat=basic/enable; type=boolean; label=Enable AutoPublishing: Publish incoming pingbacks automatically
+enableAutoPublishing = 1
+
+
diff --git a/ext_emconf.php b/ext_emconf.php
new file mode 100644 (file)
index 0000000..55ea91a
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+
+/***************************************************************
+ * Extension Manager/Repository config file for ext: "pongback"
+ *
+ * Auto generated by Extension Builder 2014-02-12
+ *
+ * Manual updates:
+ * Only the data in the array - anything else is removed by next write.
+ * "version" and "dependencies" must not be touched!
+ ***************************************************************/
+
+$EM_CONF[$_EXTKEY] = array(
+       'title' => 'Pongback',
+       'description' => 'Senden und Empfangen eines Pingbacks',
+       'category' => 'plugin',
+       'author' => 'Michael Blunck',
+       'author_email' => 'michael.blunck@phth.de',
+       'author_company' => 'PHTH',
+       'shy' => '',
+       'priority' => '',
+       'module' => '',
+       'state' => 'alpha',
+       'internal' => '',
+       'uploadfolder' => '0',
+       'createDirs' => '',
+       'modify_tables' => '',
+       'clearCacheOnLoad' => 0,
+       'lockType' => '',
+       'version' => '0.1.2',
+       'constraints' => array(
+               'depends' => array(
+                       'extbase' => '6.1.0-6.2.99',
+                       'fluid' => '6.1.0-6.2.99',
+                       'typo3' => '6.1.0-6.2.99',
+               ),
+               'conflicts' => array(
+               ),
+               'suggests' => array(
+               ),
+       ),
+);
+
+?>
\ No newline at end of file
diff --git a/ext_icon.gif b/ext_icon.gif
new file mode 100644 (file)
index 0000000..4d5dc4e
Binary files /dev/null and b/ext_icon.gif differ
diff --git a/ext_localconf.php b/ext_localconf.php
new file mode 100644 (file)
index 0000000..ed786a9
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+if (!defined('TYPO3_MODE')) {
+       die ('Access denied.');
+}
+
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+       'PHTH.' . $_EXTKEY,
+       'Pongbackfrontend',
+                      
+        array(
+               'Pingback' => 'list, show',
+               
+       ),
+       // non-cacheable actions
+       array(
+               'Pingback' => '',
+               
+       )
+);
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+       'PHTH.' . $_EXTKEY,
+       'Pongbackbackend',
+       array(
+               'Pingback' => 'list, show, delete, edit, publish, unpublish',
+               
+       ),
+       // non-cacheable actions
+       array(
+               'Pingback' => '',
+               
+       )
+);
+
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+       'PHTH.' . $_EXTKEY,
+       'server',
+       array(
+               'Pingback' => 'server',
+               
+       ),
+       // non-cacheable actions
+       array(
+               'Pingback' => 'server',
+               
+       )
+);
+
+$TYPO3_CONF_VARS['SYS']['displayErrors'] = '1';  
+$TYPO3_CONF_VARS['MAIL']['substituteOldMailAPI'] = '0';
+$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['pongback']['validatePingback'][] = 'EXT:pongback/Classes/Domain/Validator/PingbackValidator.php:PHTH\Pongback\Domain\Validator\PingbackValidator->validateTargetUri';
+$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['pongback']['validatePingback'][] = 'EXT:pongback/Classes/Domain/Validator/PingbackValidator.php:PHTH\Pongback\Domain\Validator\PingbackValidator->getInformationFromOtherWebsite';
+$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['pongback']['validatePingback'][] = 'EXT:pongback/Classes/Service/PingbackClient.php:PHTH\Pongback\Service\PingbackClient->mailPingbackArrived';
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = 'EXT:pongback/Classes/Hook/Tcemain.php:PHTH\Pongback\Hook\Tcemain';
+
+?>
\ No newline at end of file
diff --git a/ext_tables.php b/ext_tables.php
new file mode 100644 (file)
index 0000000..b80934c
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+if (!defined('TYPO3_MODE')) {
+       die ('Access denied.');
+}
+
+
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
+       $_EXTKEY,
+       'Pongbackfrontend',
+       'Pongback'
+);
+
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
+       $_EXTKEY,
+       'Server',
+       'Pongback'
+);
+
+if (TYPO3_MODE === 'BE') {
+
+       /**
+        * Registers a Backend Module
+        */
+       \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
+               'PHTH.' . $_EXTKEY,
+               'web',   // Make module a submodule of 'web'
+               'pongbackbackend',      // Submodule key
+               '',                                             // Position
+               array(
+                       'Pingback' => 'administer, show, delete, edit, publish, unpublish ',
+               ),
+               array(
+                       'access' => 'user,group',
+                       'icon'   => 'EXT:' . $_EXTKEY . '/ext_icon.gif',
+                       'labels' => 'LLL:EXT:' . $_EXTKEY . '/Resources/Private/Language/locallang_pongbackbackend.xlf',
+               )
+       );
+
+}
+
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile($_EXTKEY, 'Configuration/TypoScript', 'Pongback');
+
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('tx_pongback_domain_model_pingback', 'EXT:pongback/Resources/Private/Language/locallang_csh_tx_pongback_domain_model_pingback.xlf');
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages('tx_pongback_domain_model_pingback');
+$TCA['tx_pongback_domain_model_pingback'] = array(
+       'ctrl' => array(
+               'title' => 'LLL:EXT:pongback/Resources/Private/Language/locallang_db.xlf:tx_pongback_domain_model_pingback',
+               'label' => 'source_link',
+               'tstamp' => 'tstamp',
+               'crdate' => 'crdate',
+               'cruser_id' => 'cruser_id',
+               'dividers2tabs' => TRUE,
+               'sortby' => 'sorting',
+               'versioningWS' => 2,
+               'versioning_followPages' => TRUE,
+               'origUid' => 't3_origuid',
+               'languageField' => 'sys_language_uid',
+               'transOrigPointerField' => 'l10n_parent',
+               'transOrigDiffSourceField' => 'l10n_diffsource',
+               'delete' => 'deleted',
+               'enablecolumns' => array(
+                       'disabled' => 'hidden',
+                       'starttime' => 'starttime',
+                       'endtime' => 'endtime',
+               ),
+               'searchFields' => 'source_link,ping_client,ping_ressource,target_link,serialized_information,',
+               'dynamicConfigFile' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY) . 'Configuration/TCA/Pingback.php',
+               'iconfile' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath($_EXTKEY) . 'Resources/Public/Icons/tx_pongback_domain_model_pingback.gif'
+       ),
+);
+
+
+?>
\ No newline at end of file
diff --git a/ext_tables.sql b/ext_tables.sql
new file mode 100644 (file)
index 0000000..6ea1922
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# Table structure for table 'tx_pongback_domain_model_pingback'
+#
+CREATE TABLE tx_pongback_domain_model_pingback (
+
+       uid int(11) NOT NULL auto_increment,
+       pid int(11) DEFAULT '0' NOT NULL,
+
+       source_link varchar(255) DEFAULT '' NOT NULL,
+       ping_client varchar(255) DEFAULT '' NOT NULL,
+       ping_ressource varchar(255) DEFAULT '' NOT NULL,
+       target_link varchar(255) DEFAULT '' NOT NULL,
+       serialized_information varchar(255) DEFAULT '' NOT NULL,
+
+       tstamp int(11) unsigned DEFAULT '0' NOT NULL,
+       crdate int(11) unsigned DEFAULT '0' NOT NULL,
+       cruser_id int(11) unsigned DEFAULT '0' NOT NULL,
+       deleted tinyint(4) unsigned DEFAULT '0' NOT NULL,
+       hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
+       starttime int(11) unsigned DEFAULT '0' NOT NULL,
+       endtime int(11) unsigned DEFAULT '0' NOT NULL,
+
+       t3ver_oid int(11) DEFAULT '0' NOT NULL,
+       t3ver_id int(11) DEFAULT '0' NOT NULL,
+       t3ver_wsid int(11) DEFAULT '0' NOT NULL,
+       t3ver_label varchar(255) DEFAULT '' NOT NULL,
+       t3ver_state tinyint(4) DEFAULT '0' NOT NULL,
+       t3ver_stage int(11) DEFAULT '0' NOT NULL,
+       t3ver_count int(11) DEFAULT '0' NOT NULL,
+       t3ver_tstamp int(11) DEFAULT '0' NOT NULL,
+       t3ver_move_id int(11) DEFAULT '0' NOT NULL,
+       sorting int(11) DEFAULT '0' NOT NULL,
+       t3_origuid int(11) DEFAULT '0' NOT NULL,
+       sys_language_uid int(11) DEFAULT '0' NOT NULL,
+       l10n_parent int(11) DEFAULT '0' NOT NULL,
+       l10n_diffsource mediumblob,
+
+       PRIMARY KEY (uid),
+       KEY parent (pid),
+       KEY t3ver_oid (t3ver_oid,t3ver_wsid),
+       KEY language (l10n_parent,sys_language_uid)
+
+);
\ No newline at end of file