diff --git a/local/config/libadmin/LinkedSwissbib.ini b/local/config/libadmin/LinkedSwissbib.ini
new file mode 100644
index 0000000..e7ccad7
--- /dev/null
+++ b/local/config/libadmin/LinkedSwissbib.ini
@@ -0,0 +1,19 @@
+
+[LINKED_DATA_REPOSITORIES]
+REPOS=1
+SNL=1
+NEBIS=1
+RERO=1
+IDSBB=1
+IDSLU=1
+IDSSG=1
+IDSSG2=1
+ALEX=1
+SGBN=1
+SBT=1
+ABN=1
+BGR=1
+CCSA=1
+CHARCH=1
+LIBIB=1
+
diff --git a/local/httpd-libadmin.conf b/local/httpd-libadmin.conf
index a58258e..f27f57a 100644
--- a/local/httpd-libadmin.conf
+++ b/local/httpd-libadmin.conf
@@ -1,16 +1,21 @@
# Configuration for general VuFind base:
Alias /libadmin /usr/local/vufind/libadmin/public
- Order allow,deny
- allow from all
+
+ Order allow,deny
+ Allow from all
+
+
+ Require all granted
+
AllowOverride All
AuthType Basic
AuthName "Restricted Files"
# (Following line optional)
- AuthBasicProvider file
- AuthUserFile /usr/local/vufind/libadmin/local/passwords
- Require user libadmin
+# AuthBasicProvider file
+# AuthUserFile /usr/local/vufind/libadmin/local/passwords
+# Require user libadmin
# Uncomment the following lines, if you wish to use the Shibboleth authentication
diff --git a/module/Libadmin/Module.php b/module/Libadmin/Module.php
index f12554d..05aa72c 100644
--- a/module/Libadmin/Module.php
+++ b/module/Libadmin/Module.php
@@ -28,6 +28,25 @@ public function onBootStrap(MvcEvent $e)
{
$translator = $e->getApplication()->getServiceManager()->get('translator');
$translator->setLocale('de_DE'); /*->setFallbackLocale('en_US')*/
+
+ $app = $e->getApplication();
+ $em = $app->getEventManager()->getSharedManager();
+ $sm = $app->getServiceManager();
+
+ $em->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH, function($e) use ($sm) {
+
+ $routeParams = $e->getRouteMatch()->getParams();
+ if (array_key_exists('format',$routeParams) && strcmp($routeParams['format'],'formeta') == 0 ) {
+ $strategy = $sm->get('ViewFormetaStrategy');
+ $view = $sm->get('ViewManager')->getView();
+ $strategy->attach($view->getEventManager());
+ }
+
+ $t = "";
+
+ });
+
+
}
diff --git a/module/Libadmin/config/module.config.php b/module/Libadmin/config/module.config.php
index e0c72b7..10b5845 100644
--- a/module/Libadmin/config/module.config.php
+++ b/module/Libadmin/config/module.config.php
@@ -78,7 +78,7 @@
'constraints' => array(
'system' => '[a-zA-Z][a-zA-Z0-9_-]*',
'view' => '[a-zA-Z][a-zA-Z0-9_-]*',
- 'format' => '(xml|json|fake)' // add more formats here
+ 'format' => '(xml|json|fake|formeta)' // add more formats here
),
'defaults' => array(
'controller' => 'Libadmin\Controller\Api',
@@ -94,17 +94,20 @@
'libadmin' => __DIR__ . '/../view',
),
'strategies' => array(
- 'ViewJsonStrategy'
+ 'ViewJsonStrategy','ViewFormetaStrategy'
)
),
'service_manager' => array(
'factories' => array(
- 'Navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory'
+ 'Navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory',
+ 'ViewFormetaStrategy' => 'Libadmin\Services\View\ViewFormetaStrategyFactory',
+ 'FormetaRenderer' => 'Libadmin\Services\View\ViewFormetaRendererFactory'
),
'invokables' => array(
'export_system_vufind' => 'Libadmin\Export\System\Vufind',
'export_system_mapportal' => 'Libadmin\Export\System\MapPortal',
+ 'export_system_formeta' => 'Libadmin\Export\System\Formeta',
)
),
@@ -155,7 +158,8 @@
),
'libadmin' => array(
- 'backlinksconfig' => 'local/config/libadmin/MapPortal.ini'
+ 'backlinksconfig' => 'local/config/libadmin/MapPortal.ini',
+ 'linkedswissbibconfig' => 'local/config/libadmin/LinkedSwissbib.ini'
),
diff --git a/module/Libadmin/src/Libadmin/Export/System/Formeta.php b/module/Libadmin/src/Libadmin/Export/System/Formeta.php
new file mode 100644
index 0000000..4763ed7
--- /dev/null
+++ b/module/Libadmin/src/Libadmin/Export/System/Formeta.php
@@ -0,0 +1,164 @@
+ true,
+ 'data' => $this->getJsonPayloadData()
+ );
+ } catch (\Exception $e) {
+ $data = array(
+ 'success' => false,
+ 'data' => array(),
+ 'error' => $e->getMessage()
+ );
+ }
+
+
+ return new FormetaModel($data);
+ }
+
+ /**
+ * Extract required data from institution
+ *
+ * @param Institution $institution
+ * @return Array
+ */
+ protected function extractAllInstitutionData(Institution $institution, $groupCode)
+ {
+ $test = "";
+
+ return ['institution' => [
+
+ 'id' => $institution->getBib_code(),
+ 'sysDbId' => $institution->getId(),
+ 'sys_code' => $institution->getSys_code(),
+ 'label' => array(
+ 'de' => $institution->getLabel_de(),
+ 'fr' => $institution->getLabel_fr(),
+ 'it' => $institution->getLabel_it(),
+ 'en' => $institution->getLabel_en()
+ ),
+ 'name' => array(
+ 'de' => $institution->getName_de(),
+ 'fr' => $institution->getName_fr(),
+ 'it' => $institution->getName_it(),
+ 'en' => $institution->getName_en()
+ ),
+ 'url' => array(
+ 'de' => $institution->getUrl_de(),
+ 'fr' => $institution->getUrl_fr(),
+ 'it' => $institution->getUrl_it(),
+ 'en' => $institution->getUrl_en()
+ ),
+ 'address' => $institution->getAddress(),
+ 'zip' => $institution->getZip(),
+ 'city' => $institution->getCity(),
+ 'country' => $institution->getCountry(),
+ 'canton' => $institution->getCanton(),
+ 'website' => $institution->getWebsite(),
+ 'email' => $institution->getEmail(),
+ 'phone' => $institution->getPhone(),
+ 'skype' => $institution->getSkype(),
+ 'facebook' => $institution->getFacebook(),
+ 'coordinates' => $institution->getCoordinates(),
+ 'isil' => $institution->getIsil(),
+ 'notes' => $institution->getNotes(),
+ 'backlink' => $this->getBackLink($groupCode,$institution->getBib_code(),array())
+
+ ]];
+
+ }
+
+ /**
+ * Get grouped institution data
+ *
+ * @return Array
+ */
+ protected function getJsonPayloadData()
+ {
+ $data = array();
+ $groups = $this->getGroups();
+ //$extractInstitutionMethod = $this->getOption('all') == true ? 'extractAllInstitutionData' : 'extractInstitutionData';
+ //the whole information should always be delivered to the client
+ $extractInstitutionMethod = 'extractAllInstitutionData';
+
+
+ foreach ($groups as $group) {
+
+ $repositoryForExportDefined = $this->configLinkedRepositories->LINKED_DATA_REPOSITORIES->offsetGet($group->code);
+ if (isset($repositoryForExportDefined) && $repositoryForExportDefined ) {
+ $groupData = array(
+ 'group' => $this->extractGroupData($group),
+ 'institutions' => array()
+ );
+
+ $institutions = $this->getGroupInstitutions($group);
+
+ foreach ($institutions as $institution) {
+ $groupData['institutions'][] = $this->$extractInstitutionMethod($institution,$group->code);
+ }
+
+ $data[] = $groupData;
+
+ }
+
+
+ }
+
+ return $data;
+ }
+
+ /**
+ * @override
+ * @return void
+ */
+ public function init()
+ {
+
+ //http://localhost/libadmin/api/semanticweb/green.json?option[all]=true
+ //http://www.cambridgesemantics.com/semantic-university/getting-started
+ //documentation
+ //http://code.ohloh.net/project?pid=jZRKcGNwZOo&cid=9cCNLmy7F0s&fp=291221&mp=&projSelected=true
+ parent::init();
+
+ $config = $this->getServiceLocator()->get('config');
+ $reader = new Ini();
+ $this->configLinkedRepositories = new Config($reader->fromFile($config['libadmin']['linkedswissbibconfig']));
+
+ }
+
+
+}
+
+
diff --git a/module/Libadmin/src/Libadmin/Services/View/FormetaModel.php b/module/Libadmin/src/Libadmin/Services/View/FormetaModel.php
new file mode 100644
index 0000000..f6d76a0
--- /dev/null
+++ b/module/Libadmin/src/Libadmin/Services/View/FormetaModel.php
@@ -0,0 +1,102 @@
+getVariables();
+ if ($variables instanceof Traversable) {
+ $variables = ArrayUtils::iteratorToArray($variables);
+ }
+
+ //return Json::encode($variables);
+
+ $formetaString = null;
+
+ foreach ($variables['data'] as $groupContainer) {
+ //$groupString = "";
+ $groupString = $groupContainer['group']['code'] . ' {';
+ foreach ($groupContainer['group'] as $groupKey => $groupValue) {
+ if (!is_array($groupValue)) {
+ //$groupString .= ' \'' . $groupKey . '\' : \'' . preg_replace(array('/\'/i'),array('\\'),$groupValue) . ' \',';
+ $groupString .= ' \'' . $groupKey . '\' : \'' . preg_replace(array('/\'/i','/\\\\V/i','/\\\\E/i','/d\\\\a/i','/d\\\\i/i'),
+ array('\\\'','E','d a','d\''),$groupValue) . ' \',';
+ } else {
+ $groupString .= $this->serializeEntity($groupKey,$groupValue) ;
+ }
+
+ }
+ $formetaString .= $groupString;
+
+
+ $groupString = 'institutions {';
+
+ foreach ($groupContainer['institutions'] as $institutionsContainer) {
+ foreach ($institutionsContainer as $instKey => $instValue) {
+ if (!is_array($instValue)) {
+
+ //$groupString .= ' \'' . $instKey . '\' : \'' . preg_replace(array('/\'/i'),array('\\'),$instValue) . ' \',';
+ $groupString .= ' \'' . $instKey . '\' : \'' . preg_replace(array('/\'/i','/\\\\V/i','/\\\\E/i','/d\\\\a/i','/d\\\\i/i'),
+ array('\\\'','V','E','d a','d\''),$instValue) . '\',';
+ } else {
+
+ $groupString .= ' ' . $this->serializeEntity($instKey, $instValue) ;
+
+ }
+ }
+ }
+ $formetaString .= $groupString;
+
+ $formetaString .= '} '; // schliesse Institutions
+ $formetaString .= '}, ';
+ }
+
+ return $formetaString;
+
+ }
+
+
+ private function serializeEntity ($key, array $entity) {
+
+ $localString = ' ' . $key . ' {';
+
+ foreach ($entity as $entityKey => $entityValue)
+ {
+ if (!is_array($entityValue)) {
+ //$localString .= '\'' . $entityKey . '\' : \'' . preg_replace(array('/\'/i'),array('\\'),$entityValue) . ' \',';
+ $localString .= '\'' . $entityKey . '\' : \'' . preg_replace(array('/\'/i','/\\\\V/i','/\\\\E/i','/d\\\\a/i','/d\\\\i/i'),
+ array('\\\'','V','E','d a','d\''),$entityValue) . '\',';
+ } else {
+ //$localString .= ' {' . $this->serializeEntity($entityKey,$entityValue) . ' }, ';
+ $localString .= ' ' . $this->serializeEntity($entityKey,$entityValue) . ', ';
+ }
+ //if (!is_array($groupLiteral))
+ }
+
+ $localString .= '}, ';
+
+ return $localString;
+
+ }
+}
diff --git a/module/Libadmin/src/Libadmin/Services/View/FormetaRenderer.php b/module/Libadmin/src/Libadmin/Services/View/FormetaRenderer.php
new file mode 100644
index 0000000..e9a6c71
--- /dev/null
+++ b/module/Libadmin/src/Libadmin/Services/View/FormetaRenderer.php
@@ -0,0 +1,243 @@
+resolver = $resolver;
+ }
+
+ /**
+ * Set flag indicating whether or not to merge unnamed children
+ *
+ * @param bool $mergeUnnamedChildren
+ * @return JsonRenderer
+ */
+ public function setMergeUnnamedChildren($mergeUnnamedChildren)
+ {
+ $this->mergeUnnamedChildren = (bool) $mergeUnnamedChildren;
+ return $this;
+ }
+
+ /**
+ * Set the JSONP callback function name
+ *
+ * @param string $callback
+ * @return JsonRenderer
+ */
+ public function setJsonpCallback($callback)
+ {
+ $callback = (string) $callback;
+ if (!empty($callback)) {
+ $this->jsonpCallback = $callback;
+ }
+ return $this;
+ }
+
+ /**
+ * Returns whether or not the jsonpCallback has been set
+ *
+ * @return bool
+ */
+ public function hasJsonpCallback()
+ {
+ return (null !== $this->jsonpCallback);
+ }
+
+ /**
+ * Should we merge unnamed children?
+ *
+ * @return bool
+ */
+ public function mergeUnnamedChildren()
+ {
+ return $this->mergeUnnamedChildren;
+ }
+
+ /**
+ * Renders values as JSON
+ *
+ * @todo Determine what use case exists for accepting both $nameOrModel and $values
+ * @param string|Model $nameOrModel The script/resource process, or a view model
+ * @param null|array|\ArrayAccess $values Values to use during rendering
+ * @throws Exception\DomainException
+ * @return string The script output.
+ */
+ public function render($nameOrModel, $values = null)
+ {
+ // use case 1: View Models
+ // Serialize variables in view model
+ if ($nameOrModel instanceof Model) {
+ if ($nameOrModel instanceof FormetaModel) {
+ $values = $nameOrModel->serialize();
+ }
+
+ /*
+ if ($nameOrModel instanceof JsonModel) {
+ $children = $this->recurseModel($nameOrModel, false);
+ $this->injectChildren($nameOrModel, $children);
+ $values = $nameOrModel->serialize();
+ } else {
+ $values = $this->recurseModel($nameOrModel);
+ $values = Json::encode($values);
+ }
+
+ if ($this->hasJsonpCallback()) {
+ $values = $this->jsonpCallback . '(' . $values . ');';
+ }
+ */
+ return $values;
+ }
+
+ // use case 2: $nameOrModel is populated, $values is not
+ // Serialize $nameOrModel
+ if (null === $values) {
+ if (!is_object($nameOrModel) || $nameOrModel instanceof JsonSerializable) {
+ $return = Json::encode($nameOrModel);
+ } elseif ($nameOrModel instanceof Traversable) {
+ $nameOrModel = ArrayUtils::iteratorToArray($nameOrModel);
+ $return = Json::encode($nameOrModel);
+ } else {
+ $return = Json::encode(get_object_vars($nameOrModel));
+ }
+
+ if ($this->hasJsonpCallback()) {
+ $return = $this->jsonpCallback . '(' . $return . ');';
+ }
+ return $return;
+ }
+
+ // use case 3: Both $nameOrModel and $values are populated
+ throw new Exception\DomainException(sprintf(
+ '%s: Do not know how to handle operation when both $nameOrModel and $values are populated',
+ __METHOD__
+ ));
+ }
+
+ /**
+ * Can this renderer render trees of view models?
+ *
+ * Yes.
+ *
+ * @return true
+ */
+ public function canRenderTrees()
+ {
+ return true;
+ }
+
+ /**
+ * Retrieve values from a model and recurse its children to build a data structure
+ *
+ * @param Model $model
+ * @param bool $mergeWithVariables Whether or not to merge children with
+ * the variables of the $model
+ * @return array
+ */
+ protected function recurseModel(Model $model, $mergeWithVariables = true)
+ {
+ $values = array();
+ if ($mergeWithVariables) {
+ $values = $model->getVariables();
+ }
+
+ if ($values instanceof Traversable) {
+ $values = ArrayUtils::iteratorToArray($values);
+ }
+
+ if (!$model->hasChildren()) {
+ return $values;
+ }
+
+ $mergeChildren = $this->mergeUnnamedChildren();
+ foreach ($model as $child) {
+ $captureTo = $child->captureTo();
+ if (!$captureTo && !$mergeChildren) {
+ // We don't want to do anything with this child
+ continue;
+ }
+
+ $childValues = $this->recurseModel($child);
+ if ($captureTo) {
+ // Capturing to a specific key
+ // TODO please complete if append is true. must change old
+ // value to array and append to array?
+ $values[$captureTo] = $childValues;
+ } elseif ($mergeChildren) {
+ // Merging values with parent
+ $values = array_replace_recursive($values, $childValues);
+ }
+ }
+ return $values;
+ }
+
+ /**
+ * Inject discovered child model values into parent model
+ *
+ * @todo detect collisions and decide whether to append and/or aggregate?
+ * @param Model $model
+ * @param array $children
+ */
+ protected function injectChildren(Model $model, array $children)
+ {
+ foreach ($children as $child => $value) {
+ // TODO detect collisions and decide whether to append and/or aggregate?
+ $model->setVariable($child, $value);
+ }
+ }
+}
diff --git a/module/Libadmin/src/Libadmin/Services/View/FormetaStrategy.php b/module/Libadmin/src/Libadmin/Services/View/FormetaStrategy.php
new file mode 100644
index 0000000..bc82375
--- /dev/null
+++ b/module/Libadmin/src/Libadmin/Services/View/FormetaStrategy.php
@@ -0,0 +1,134 @@
+renderer = $renderer;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function attach(EventManagerInterface $events, $priority = 1)
+ {
+ $this->listeners[] = $events->attach(ViewEvent::EVENT_RENDERER, array($this, 'selectRenderer'), $priority);
+ $this->listeners[] = $events->attach(ViewEvent::EVENT_RESPONSE, array($this, 'injectResponse'), $priority);
+ }
+
+ /**
+ * Set the content-type character set
+ *
+ * @param string $charset
+ * @return FormetaStrategy
+ */
+ public function setCharset($charset)
+ {
+ $this->charset = (string) $charset;
+ return $this;
+ }
+
+ /**
+ * Retrieve the current character set
+ *
+ * @return string
+ */
+ public function getCharset()
+ {
+ return $this->charset;
+ }
+
+ /**
+ * Detect if we should use the JsonRenderer based on model type and/or
+ * Accept header
+ *
+ * @param ViewEvent $e
+ * @return null|JsonRenderer
+ */
+ public function selectRenderer(ViewEvent $e)
+ {
+ $model = $e->getModel();
+
+ if (!$model instanceof FormetaModel) {
+ // no JsonModel; do nothing
+ return;
+ }
+
+ // JsonModel found
+ return $this->renderer;
+ }
+
+ /**
+ * Inject the response with the JSON payload and appropriate Content-Type header
+ *
+ * @param ViewEvent $e
+ * @return void
+ */
+ public function injectResponse(ViewEvent $e)
+ {
+ $renderer = $e->getRenderer();
+ if ($renderer !== $this->renderer) {
+ // Discovered renderer is not ours; do nothing
+ return;
+ }
+
+ $result = $e->getResult();
+ if (!is_string($result)) {
+ // We don't have a string, and thus, no JSON
+ return;
+ }
+
+ // Populate response
+ $response = $e->getResponse();
+ $response->setContent($result);
+ $headers = $response->getHeaders();
+
+ if ($this->renderer->hasJsonpCallback()) {
+ $contentType = 'application/text';
+ } else {
+ $contentType = 'application/text';
+ }
+
+ $contentType .= '; charset=' . $this->charset;
+ $headers->addHeaderLine('content-type', $contentType);
+
+ if (in_array(strtoupper($this->charset), $this->multibyteCharsets)) {
+ $headers->addHeaderLine('content-transfer-encoding', 'BINARY');
+ }
+ }
+}
diff --git a/module/Libadmin/src/Libadmin/Services/View/ViewFormetaRendererFactory.php b/module/Libadmin/src/Libadmin/Services/View/ViewFormetaRendererFactory.php
new file mode 100644
index 0000000..82daca3
--- /dev/null
+++ b/module/Libadmin/src/Libadmin/Services/View/ViewFormetaRendererFactory.php
@@ -0,0 +1,21 @@
+get('FormetaRenderer');
+ $formetastrategy = new FormetaStrategy($formetaRenderer);
+ return $formetastrategy;
+ }
+}