6 * Copyright 2012-2013, Olivier Berger & Institut Mines-Telecom
7 * Copyright 2013, Roland Mas
9 * This file is part of FusionForge. FusionForge is free software;
10 * you can redistribute it and/or modify it under the terms of the
11 * GNU General Public License as published by the Free Software
12 * Foundation; either version 2 of the Licence, or (at your option)
15 * FusionForge is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 // This Plugin publishes meta-data about the public projects hosted on the forge
26 // as RDF conforming to the ADMS.SW 1.0 specifications :
27 // https://joinup.ec.europa.eu/asset/adms_foss/release/release100
29 require_once('common/include/TroveCat.class.php');
30 require_once('common/frs/FRSFileType.class.php');
31 require_once $gfplugins.'admssw/common/RDFedFRSPackage.class.php' ;
32 require_once('common/include/rdfutils.php');
33 include_once("Graphite.php");
35 class admsswPlugin extends Plugin {
37 public static $PAGING_LIMIT = 50;
39 //var $trovecat_id_index; // cat_id to TroveCat instances
40 var $trovecat_id_to_shortname; // cat_id to shortname
41 var $trovecat_id_to_path; // cat_id to path
46 * @param number $id plugin identifier
48 public function __construct($id=0) {
50 $this->name = "admssw";
51 $this->text = "ADMS.SW"; // To show in the tabs, use...
53 // The standard RDF namespaces that will be used in the plugin
55 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
56 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
57 'doap' => 'http://usefulinc.com/ns/doap#',
58 'dcterms' => 'http://purl.org/dc/terms/',
59 'admssw' => 'http://purl.org/adms/sw/',
60 'adms' => 'http://www.w3.org/ns/adms#',
61 'foaf' => 'http://xmlns.com/foaf/0.1/',
62 'schema' => 'http://schema.org/',
63 'rad' => 'http://www.w3.org/ns/rad#',
64 'ldp' => 'http://www.w3.org/ns/ldp#'
67 //$this->trovecat_id_index = array();
68 $this->trovecat_id_to_shortname = array();
69 $this->trovecat_id_to_path = array();
71 // Add the doaprdf plugin's namespaces
72 $doaprdfplugin = plugin_get_object ("doaprdf");
73 $ns = $doaprdfplugin->doapNameSpaces();
74 foreach($ns as $s => $u)
76 if (! in_array($u, $this->ns)) {
81 $this->_addHook("project_rdf_metadata"); // will provide some RDF metadata for the project's DOAP profile to 'doaprdf' plugin
82 $this->_addHook("alt_representations"); // declares a link to itself in the link+meta HTML headers of /projects and /softwaremap
83 $this->_addHook("script_accepted_types"); // supported alternate content-types (Accept HTTP header values)
84 $this->_addHook("content_negociated_projects_list"); // registers to be able to return content-negociated content for /projects/...
85 $this->_addHook("softwaremap_links"); // display additional submenu in the softwaremap tool
86 $this->_addHook("project_after_description"); // displays additional info in the project info widget
87 $this->_addHook("content_negociated_trove_list"); // generates the RDF document containing the trove categories as SKOS
88 $this->_addHook("content_negociated_frs_index"); // generates the public projects list/index as RDF
89 $this->_addHook("content_negociated_frs_download_file"); // generates the RDF meta-data about a FRS downloadable file
93 // General conneg related or other hook callbacks
97 * Declares itself as accepting RDF XML or Turtle on /projects and other scripts ...
99 * @param unknown_type $params
101 public function script_accepted_types (&$params) {
102 $script = $params['script'];
103 if ($script == 'projects_list' || $script == 'admssw_full' || $script == 'trove_list' || $script == 'frs_index' || $script == 'frs_download_file') {
104 $params['accepted_types'][] = 'application/rdf+xml';
105 $params['accepted_types'][] = 'text/turtle';
110 * Declares a link to itself in the link+meta HTML headers of /projects and /softwaremap
112 * @param unknown_type $params
114 public function alt_representations (&$params) {
115 $script_name = $params['script_name'];
116 $php_self = $params['php_self'];
117 if ($php_self == '/softwaremap/trove_list.php') {
118 $params['return'][] = '<link rel="alternate" type="application/rdf+xml" title="ADMS.SW RDF Data" href="'. util_make_url ("/plugins/admssw/trove.php") .'"/>';
119 $params['return'][] = '<link rel="alternate" type="text/turtle" title="ADMS.SW RDF Data" href="'. util_make_url ("/plugins/admssw/trove.php") .'"/>';
121 elseif ($script_name == '/softwaremap') {
122 $params['return'][] = '<link rel="alternate" type="application/rdf+xml" title="ADMS.SW RDF Data" href="'. util_make_url ("/projects") .'"/>';
123 $params['return'][] = '<link rel="alternate" type="text/turtle" title="ADMS.SW RDF Data" href="'. util_make_url ("/projects") .'"/>';
125 else if($script_name == '/projects') {
126 $params['return'][] = '<link rel="alternate" type="application/rdf+xml" title="ADMS.SW RDF Data" href="'. util_make_url ($php_self) .'"/>';
127 $params['return'][] = '<link rel="alternate" type="text/turtle" title="ADMS.SW RDF Data" href="'. util_make_url ($php_self) .'"/>';
132 * Add a new link to the softwaremap submenu
134 * @param array $params
136 public function softwaremap_links (&$params) {
138 $params['TITLES'][] = _('ADMS.SW meta-data');
139 $params['URLS'][] = '/plugins/'. $this->name .'/index.php';
140 $params['ATTRS'][] = array('title' => _('ADMS.SW RDF meta-data about forge projects.'), 'class' => 'tabtitle');
144 * Add a line in the project infos widget in the project home
146 * @param array $params
148 public function project_after_description (&$params) {
149 $group_id = $params['group_id'];
150 print '<br />'. sprintf( _('Preview <a href="%1$s">ADMS.SW meta-data</a> about the project'), util_make_url ('/plugins/'. $this->name .'/projectturtle.php?group_id='.$group_id));
159 * Returns namespaces used in ADMS.SW
161 * @return array the namespaces associative array
163 public function admsswNameSpaces() {
168 * Initialize Graphite graph's namespaces
170 private function graphSetAdmsswNameSpaces(&$graph) {
171 $ns = $this->admsswNameSpaces();
172 foreach($ns as $s => $u)
174 $graph->ns( $s, $u );
178 static function repositoryUri() {
179 return util_make_url ('/projects#repo');
183 // Project related methods and callbacks
187 * Provides an HTML preview of a project's ADMS.SW meta-data looking like turtle
189 * @param int $group_id
191 public function htmlPreviewProjectAsTurtle($group_id) {
195 $graph = new Graphite();
197 $this->graphSetAdmsswNameSpaces($graph);
199 $resourceindex = $this->addProjectResourceToGraph($graph, $group_id, $detailed);
201 return $graph->dump();
205 * Provides an ARC2 resource index of a project's ADMS.SW meta-data
207 * @param int $group_id
209 private function addProjectResourceToGraph(&$graph, $group_id, $detailed = false) {
211 // part of the work is done by the doaprdf plugin, which will in turn call us back (see project_rdf_metadata)
212 $doaprdfplugin = plugin_get_object ("doaprdf");
214 $ns = $this->admsswNameSpaces();
216 $resourceindex = $doaprdfplugin->getProjectResourceIndex($group_id, $ns, $detailed);
218 // update the namespaces if they happen to get updated in between
219 foreach($ns as $s => $u)
221 if (! in_array($u, $this->ns)) {
226 $count = $graph->addTriples( ARC2::getTriplesFromIndex($resourceindex) );
232 * Improves the DOAP description made by doaprdf (ARC2 resource) to add ADMS.SW meta-data for a project
234 * @param unknown_type $params
236 * This is a hook callback so part of the resource construction is made in the doaprdf plugin
238 public function project_rdf_metadata (&$params) {
240 # TODO : check that the passed in_Resource is indeed a doap:Project
241 $group_id = $params['group'];
243 // Update the prefixes by ADMS.SW ones
244 $new_prefixes = $this->admsswNameSpaces();
245 foreach($new_prefixes as $s => $u)
247 if (! isset($params['prefixes'][$u])) {
248 $params['prefixes'][$u] = $s;
253 if ($params['details'] == 'full') {
257 // The ARC2 RDF_Resource already initialized by doaprdf plugin
258 $res = $params['in_Resource'];
260 // we could save the type doap:Project in such case, as there's an equivalence, but not sure all consumers do reasoning
261 $types = array('doap:Project', 'admssw:SoftwareProject');
262 rdfutils_setPropToUri($res, 'rdf:type', $types);
265 // Handle project tags
267 if (forge_get_config('use_project_tags')) {
268 $group = group_get_object($group_id);
269 $tags_list = $group->getTags();
271 // connect to FusionForge internals
272 $pm = ProjectManager::instance();
273 $project = $pm->getProject($group_id);
276 $tags = split(', ',$tags_list);
278 // reuse the same as dcterms:subject until further specialization of adms.sw keywords
279 $res->setProp('rad:keyword', $tags);
282 $project_description = $project->getDescription();
283 if($project_description) {
284 // it seems that doap:description is not equivalent to dcterms:description, so repeat
285 $res->setProp('dcterms:description', $project_description);
288 // Handle trove categories
289 $trovecaturis=array('admssw:intendedAudience' => array(),
290 'admssw:locale' => array(),
291 'admssw:userInterfaceType' => array(),
292 'admssw:programmingLanguage' => array(),
293 'schema:operatingSystem' => array(),
294 'admssw:status' => array(),
295 'rad:theme' => array());
296 $trovecats = TroveCat::getProjectCats($group_id);
297 foreach($trovecats as $trovecat) {
298 $cat_id = $trovecat->getId();
299 if(!isset($this->trovecat_id_to_shortname[$cat_id])) {
300 $this->trovecat_id_to_shortname[$cat_id] = $trovecat->getShortName();
302 $idsfullpath = $trovecat->getIdsFullPath();
303 $folders_ids = explode(" :: ", $idsfullpath);
305 foreach ($folders_ids as $id) {
306 if (! isset($this->trovecat_id_to_shortname[$id])) {
307 $supercat = new TroveCat($id);
308 $this->trovecat_id_to_shortname[$id] = $supercat->getShortName();
310 $paths[] = $this->trovecat_id_to_shortname[$id];
312 $path=implode('/', $paths);
313 $this->trovecat_id_to_path[$cat_id] = $path;
314 $trovecaturi = util_make_url ('/softwaremap/trove/'.$path);
315 $rootcatid = $trovecat->getRootCatId();
316 $rootcatshortname = $this->trovecat_id_to_shortname[$rootcatid];
317 // This is a bit hackish
318 switch ($rootcatshortname) {
319 case 'developmentstatus':
320 $trovecaturis['admssw:status'][] = $trovecaturi;
323 $trovecaturis['admssw:intendedAudience'][] = $trovecaturi;
326 $trovecaturis['dcterms:license'][] = $trovecaturi;
329 $trovecaturis['admssw:locale'][] = $trovecaturi;
332 $trovecaturis['schema:operatingSystem'][] = $trovecaturi;
335 $trovecaturis['admssw:programmingLanguage'][] = $trovecaturi;
338 $trovecaturis['rad:theme'][] = $trovecaturi;
342 foreach ($trovecaturis as $prop => $uris) {
344 rdfutils_setPropToUri($res, $prop, $uris);
348 $res->setProp('rdfs:comment', "Generated with the doaprdf and admssw plugins of fusionforge");
350 rdfutils_setPropToUri($res, 'dcterms:isPartOf', admsswPlugin::repositoryUri());
352 // Handle project members
353 $admins = $project->getAdmins() ;
354 $members = $project->getUsers() ;
355 $contributors_uris = array();
356 foreach ($admins as $u) {
357 $contributor_uri = util_make_url_u ($u->getUnixName(),$u->getID());
358 $contributor_uri = rtrim($contributor_uri, '/');
359 $contributor_uri = $contributor_uri . '#person';
360 if (! in_array($contributor_uri, $contributors_uris) ) {
361 $contributors_uris[] = $contributor_uri;
364 foreach ($members as $u) {
365 $contributor_uri = util_make_url_u ($u->getUnixName(),$u->getID());
366 $contributor_uri = rtrim($contributor_uri, '/');
367 $contributor_uri = $contributor_uri . '#person';
368 if (! in_array($contributor_uri, $contributors_uris) ) {
369 $contributors_uris[] = $contributor_uri;
372 rdfutils_setPropToUri($res, 'schema:contributor', $contributors_uris);
374 // Handle FRS releases
375 $release_uris = array();
376 $frs_packages = get_rdfed_frs_packages($project);
377 foreach ($frs_packages as $frs_package) {
378 //print_r($frs_package);
380 if($frs_package->isPublic() && $frs_package->getStatus() == 1) {
381 $package_name = $frs_package->getFileName();
383 $frs_releases = $frs_package->getReleases();
384 foreach ($frs_releases as $frs_release) {
385 if( $frs_release->getStatus() == 1 ) {
386 //print_r($frs_release);
387 $release_uris[] = $frs_release->getUri();
392 if(count($release_uris)) {
393 rdfutils_setPropToUri($res, 'doap:release', $release_uris);
395 // The releases aren't discoverable by follow your nose yet, so add the proper document/script URL to use
396 rdfutils_setPropToUri($res, 'rdfs:seeAlso', util_make_url ('/frs/?group_id='.$group_id));
398 $params['out_Resources'][] = $res;
401 $graph = new Graphite();
402 $this->graphSetAdmsswNameSpaces($graph);
404 $this->addProjectFrsResourcesToGraph($graph, $group_id);
406 $subjects = $graph->allSubjects();
407 foreach ($subjects as $subject) {
408 $resource = $graph->resource( $subject );
409 $triples = $resource->toArcTriples();
411 $index = ARC2::getSimpleIndex($triples, false);
413 $res = ARC2::getResource();
414 $res->setIndex($index);
416 $params['out_Resources'][] = $res;
425 // Project list / SoftwareRepository related methods
429 * Returns the number of projects in a project index
431 public function getProjectListSize() {
432 // same as for trove's full list
433 $projects = get_public_active_projects_asc();
434 return count($projects);
438 * Provides a Graphite graph for resource(s) representing the ADMS.SW SoftwareRepository
440 * @param string URI of the document to use
441 * @param bool are projects to be fully described or just a URI of their resource
442 * @param $chunk number of the chunk to be returned in case of paging
443 * @param $chunksize size of chunks in case of paging
445 public function getProjectListResourcesGraph($documenturi, $detailed=false, $chunk=null, $chunksize=null) {
447 // Construct an ARC2_Resource containing the project's RDF (DOAP) description
448 $ns = $this->admsswNameSpaces();
454 $res = ARC2::getResource($conf);
455 $res->setURI( admsswPlugin::repositoryUri() );
457 // $res->setRel('rdf:type', 'admssw:SoftwareRepository');
458 rdfutils_setPropToUri($res, 'rdf:type', 'admssw:SoftwareRepository');
460 //$res->setProp('doap:name', $projectname);
461 rdfutils_setPropToUri($res, 'adms:accessURL', util_make_url ("/softwaremap/") );
462 $forge_name = forge_get_config ('forge_name');
463 $ff = new FusionForge();
464 $res->setProp('dcterms:description', 'Public projects in the '. $ff->software_name .' Software Map on '. $forge_name );
465 $res->setProp('rdfs:label', $forge_name .' public projects');
466 $res->setProp('adms:supportedSchema', 'ADMS.SW v1.0');
468 // same as for trove's full list
469 $projects = get_public_active_projects_asc();
472 if ( isset($chunk) && isset($chunksize) ) {
473 // TODO : do some checks on $chunk $chunksize values
474 // if ( ($chunk < 1) && ($chunksize >= 1) ) {
477 $projects_chunks = array_chunk($projects, $chunksize);
478 $projects = $projects_chunks[$chunk-1];
481 $proj_uris = array();
482 foreach ($projects as $row_grp) {
483 $proj_uri = util_make_url_g(strtolower($row_grp['unix_group_name']),$row_grp['group_id']).'#project';
484 $proj_uris[] = $proj_uri;
486 if(count($proj_uris)) {
487 rdfutils_setPropToUri($res, 'dcterms:hasPart', $proj_uris);
490 $graph = new Graphite();
491 $this->graphSetAdmsswNameSpaces($graph);
493 $count = $graph->addTriples( ARC2::getTriplesFromIndex($res->index) );
495 // if needed, provide also full details about the projects
496 foreach ($projects as $row_grp) {
497 $group_id = $row_grp['group_id'];
498 //$proj_uri = util_make_url_g(strtolower($row_grp['unix_group_name']),$row_grp['group_id']);
499 $count = $this->addProjectResourceToGraph($graph, $row_grp['group_id'], $detailed);
502 $this->graphSetAdmsswNameSpaces($graph);
504 // The document the document itself
505 $res = ARC2::getResource($conf);
506 $res->setURI( $documenturi );
507 rdfutils_setPropToUri($res, 'rdf:type', 'foaf:Document');
508 rdfutils_setPropToUri($res, 'foaf:primaryTopic', admsswPlugin::repositoryUri() );
509 rdfutils_setPropToXSDdateTime($res, 'dcterms:created', date('c'));
510 $res->setProp('dcterms:title', "ADMS.SW full dump" );
512 $count = $graph->addTriples( ARC2::getTriplesFromIndex($res->index) );
518 * Returns the size of the pages for paged documents (project indexes or full projects dump)
520 public function getPagingLimit() {
521 return self::$PAGING_LIMIT;
525 * Process the paging parameters and eventually redirect, ala LDP
527 * When there are too many projects to be displayed, it will redirect to the first page : ?page=1
528 * This can be overriden with the ?allatonce parameter
530 public function process_paging_params_or_redirect($projectsnum, $pl) {
532 $p = getIntFromRequest('page', 0);
534 if ( null !== getStringFromRequest('allatonce', null)) {
535 $pl = $projectsnum + 1;
539 // force paging if too many projects
540 if ( ($projectsnum > $pl) && ! ($p > 0) ) {
541 header("Location: ?page=1");
542 header($_SERVER["SERVER_PROTOCOL"]." 303 See Other",true,303);
546 // if paging is requested
548 $maxpage = ceil($projectsnum / $pl);
550 header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found",true,404);
551 printf("Page %d requested is beyond the maximum %d !", $p, $maxpage);
561 * Provides either an HTML preview looking like turtle, or plain RDF of the ADMS.SW SoftwareRepository meta-data
563 * @param string URL of the RDF document
564 * @param string expected content type for the document
565 * @param int page number. If null, means no paging but full document
566 * @param int page length : how many projects per page
567 * @param bool if has to provide full details about projects
568 * @param string URL of the HTML script if different than the RDF document
570 public function getProjectsListDisplay($documenturi, $content_type, $p, $pl, $detailed=false, $scripturl=false) {
575 $scripturl = $documenturi;
581 // if paging is requested
585 $pageuri = $documenturi . '?page='. (string)$p;
588 $projectsnum = $this->getProjectListSize();
590 // process as in content_negociated_projects_list but with full details
591 $graph = $this->getProjectListResourcesGraph($documenturi, $detailed, $chunk, $chunksize);
594 if($content_type != 'text/html') {
597 $ns = $this->admsswNameSpaces();
602 $res = ARC2::getResource($conf);
603 $res->setURI( $pageuri );
604 rdfutils_setPropToUri($res, 'rdf:type', 'ldp:Page');
606 if( $p < ceil($projectsnum / $pl) ) {
607 $nextpageuri = $documenturi . '?page=' . (string) ($p + 1);
608 rdfutils_setPropToUri($res, 'ldp:nextPage', $nextpageuri);
611 rdfutils_setPropToUri($res, 'ldp:nextPage', 'rdf:nil');
613 rdfutils_setPropToUri($res, 'ldp:pageOf', $documenturi);
615 $count = $graph->addTriples( ARC2::getTriplesFromIndex($res->index) );
618 // We can support only RDF as RDF+XML or Turtle
619 if ($content_type == 'text/turtle' || $content_type == 'application/rdf+xml') {
620 if ($content_type == 'text/turtle') {
621 $doc = $graph->serialize($serializer="Turtle")."\n";
623 if ($content_type == 'application/rdf+xml') {
624 $doc = $graph->serialize()."\n";
628 header('HTTP/1.1 406 Not Acceptable',true,406);
629 print $graph->dumpText();
635 $doc = '<p>'. _('The following is a preview of (machine-readable) RDF meta-data, in Turtle format (see at the bottom for more details)') .'<br />';
637 $html_limit = '<span style="text-align:center;font-size:smaller">';
638 $html_limit .= sprintf(_('<strong>%1$s</strong> projects in result set.'), $projectsnum);
639 // only display pages stuff if there is more to display
640 if ($projectsnum > $pl) {
641 $html_limit .= html_trove_limit_navigation_box($scripturl, $projectsnum, $pl, $p);
643 $html_limit .= '</span>';
647 $doc .= $graph->dump();
649 $doc .= _('To access this RDF document, you may use, for instance :<br />');
650 $doc .= '<tt>$ curl -L -H "Accept: text/turtle" '. $documenturi .'</tt><br />';
652 $doc .= _('This may redirect to several pages documents in case of too big number of results (observing the LDP paging specifications).<br /><br />');
654 $doc .= _('Alternatively, if you are sure you want the full dump in one single document, use :<br />');
655 $doc .= '<tt>$ curl -H "Accept: text/turtle" "'. $documenturi .'?allatonce"</tt>';
662 * Outputs the public projects list as ADMS.SW for /projects
664 * @param unknown_type $params
666 * This has a counterpart in /plugins/admssw/projectsturtle.php which previews the Turtle as HTML
668 public function content_negociated_projects_list (&$params) {
671 $accept = $params['accept'];
673 // we are asked for RDF either as RDF+XML or Turtle
674 if($accept == 'application/rdf+xml' || $accept == 'text/turtle') {
676 // We will return RDF
677 $params['content_type'] = $accept;
679 $documenturi = util_make_url ("/projects");
682 $pl = admsswPlugin::$PAGING_LIMIT;
684 $projectsnum = $this->getProjectListSize();
686 $p = $this->process_paging_params_or_redirect($projectsnum, $pl);
688 $doc = $this->getProjectsListDisplay($documenturi, $accept, $p, $pl);
690 $params['content'] = $doc . "\n";
697 // Trove related methods
701 * Provides a Graphite graph for resource(s) representing the trove categories as SKOS concepts
704 private function getTroveListResourcesGraph() {
706 // Construct an ARC2_Resource containing the project's RDF (DOAP) description
708 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
709 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
710 'skos' => 'http://www.w3.org/2004/02/skos/core#'
718 $graph = new Graphite();
719 $this->graphSetAdmsswNameSpaces($graph);
721 $rootcats = TroveCat::getAllRoots();
723 foreach($rootcats as $rootcat) {
725 // First the ConceptScheme itself
727 $conceptschemeres = ARC2::getResource($conf);
729 $scheme_shortname = $rootcat->getShortName();
730 $conceptscheme_uri = util_make_url ('/softwaremap/trove/'.$scheme_shortname);
731 $conceptschemeres->setURI( $conceptscheme_uri );
733 // $res->setRel('rdf:type', 'doap:Project');
734 rdfutils_setPropToUri($conceptschemeres, 'rdf:type', 'skos:ConceptScheme');
736 $conceptschemeres->setProp('skos:prefLabel', $rootcat->getFullName());
737 $conceptschemeres->setProp('skos:definition', $rootcat->getDescription());
739 $count = $graph->addTriples( ARC2::getTriplesFromIndex($conceptschemeres->index) );
742 $subcats = $rootcat->listSubTree();
744 // memorize a few indexes
746 foreach($subcats as $subcat) {
747 $cat_id = $subcat->getId();
748 //$this->trovecat_id_index[$cat_id] = &$subcat;
750 $this->trovecat_id_to_shortname[$cat_id] = $subcat->getShortName();
753 foreach($subcats as $subcat) {
754 $cat_id = $subcat->getId();
756 $idsfullpath = $subcat->getIdsFullPath();
758 $folders_ids = explode(" :: ", $idsfullpath);
761 foreach ($folders_ids as $id) {
762 if (isset($this->trovecat_id_to_shortname[$id])) {
763 $paths[] = $this->trovecat_id_to_shortname[$id];
766 $path=implode('/', $paths);
768 $this->trovecat_id_to_path[$cat_id] = $path;
771 // Now, for all Concepts in this ConceptScheme
773 foreach($subcats as $subcat) {
774 $conceptres = ARC2::getResource($conf);
776 $path = $this->trovecat_id_to_path[$subcat->getId()];
777 $conceptres->setURI( util_make_url ('/softwaremap/trove/'.$scheme_shortname.'/'.$path) );
779 // $res->setRel('rdf:type', 'doap:Project');
780 rdfutils_setPropToUri($conceptres, 'rdf:type', 'skos:Concept');
782 rdfutils_setPropToUri($conceptres, 'skos:inScheme', $conceptscheme_uri);
784 $conceptres->setProp('skos:prefLabel', $subcat->getFullName());
785 $conceptres->setProp('skos:definition', $subcat->getDescription());
787 $parentid = $subcat->getParentId();
788 $rootparentid = $subcat->getRootCatId();
790 if ($parentid != $rootparentid) {
791 $parentpath = $this->trovecat_id_to_path[$parentid];
792 rdfutils_setPropToUri($conceptres, 'skos:broader', util_make_url ('/softwaremap/trove/'.$scheme_shortname.'/'.$parentpath) );
795 $count = $graph->addTriples( ARC2::getTriplesFromIndex($conceptres->index) );
804 * Provides an HTML preview of the trove categories as SKOS looking like turtle
807 public function htmlPreviewTroveCatsAsTurtle() {
808 $graph = $this->getTroveListResourcesGraph();
810 return $graph->dump();
814 * Outputs the trove categories as SKOS
816 * @param unknown_type $params
818 public function content_negociated_trove_list (&$params) {
820 $accept = $params['accept'];
822 // we are asked for RDF either as RDF+XML or Turtle
823 if($accept == 'application/rdf+xml' || $accept == 'text/turtle') {
826 // We will return RDF
827 $params['content_type'] = $accept;
829 $graph = $this->getTroveListResourcesGraph();
831 if ($accept == 'text/turtle') {
832 $doc = $graph->serialize($serializer="Turtle");
834 if ($accept == 'application/rdf+xml') {
835 $doc = $graph->serialize();
838 $params['content'] = $doc . "\n";
845 // FRS related methods
849 * Add RDF resources to a Graphite graph for the File Release system
851 * @param Graphite graph to be updated
852 * @param int group id
853 * @param int optional release id
855 private function addProjectFrsResourcesToGraph(&$graph, $group_id, $release_id = false) {
857 $group = group_get_object($group_id);
859 // if we are passed a release ID, then only process that particular release
862 $frs_release = rdfed_frsrelease_get_object($release_id);
864 // Don't produce RDF for hidden releases
865 if( $frs_release->getStatus() == 1 ) {
866 $frs_package = $frs_release->getFRSPackage();
868 // Only produce RDF for releases of public and not hidden packages
869 if ($frs_package->isPublic() && $frs_package->getStatus() == 1) {
871 $frs_release->saveToGraph($graph);
877 // then produce RDF for all the project's packages
878 $frs_packages = get_rdfed_frs_packages($group);
880 foreach($frs_packages as $frs_package) {
881 // well actually, only for public and not hidden packages
882 if ($frs_package->isPublic() && $frs_package->getStatus() == 1) {
884 $frs_package->saveToGraph($graph);
893 * Outputs the public projects releases as ADMS.SW for /frs
895 * @param unknown_type $params
897 public function content_negociated_frs_index (&$params) {
899 $accept = $params['accept'];
901 // we are asked for RDF either as RDF+XML or Turtle
902 if($accept == 'application/rdf+xml' || $accept == 'text/turtle') {
905 // We will return RDF
906 $params['content_type'] = $accept;
908 $group_id = $params['group_id'];
909 $release_id = $params['release_id'];
911 $graph = new Graphite();
912 $this->graphSetAdmsswNameSpaces($graph);
914 $this->addProjectFrsResourcesToGraph($graph, $group_id, $release_id);
916 if ($accept == 'text/turtle') {
917 $doc = $graph->serialize($serializer="Turtle");
919 if ($accept == 'application/rdf+xml') {
920 $doc = $graph->serialize();
923 $params['content'] = $doc . "\n";
929 * Outputs the public downloadable files as ADMS.SW SoftwarePackages for /frs/download.php...
931 * @param unknown_type $params
933 public function content_negociated_frs_download_file (&$params) {
935 $accept = $params['accept'];
937 // we are asked for RDF either as RDF+XML or Turtle
938 if($accept == 'application/rdf+xml' || $accept == 'text/turtle') {
940 // We will return RDF
941 $params['content_type'] = $accept;
943 $file_id = $params['file_id'];
945 $frs_file = rdfed_frsfile_get_object($file_id);
947 session_redirect404();
950 $frs_release = $frs_file->getFRSRelease();
951 $frs_package = $frs_release->getFRSPackage();
952 $group = $frs_package->getGroup();
954 $graph = new Graphite();
955 $this->graphSetAdmsswNameSpaces($graph);
957 // We only accept files in public and non-hidden project's packages
958 if ($frs_package->isPublic() && $frs_package->getStatus() == 1) {
959 $frs_file->saveToGraph($graph);
962 if ($accept == 'text/turtle') {
963 $doc = $graph->serialize($serializer="Turtle");
965 if ($accept == 'application/rdf+xml') {
966 $doc = $graph->serialize();
969 $params['content'] = $doc . "\n";
977 // c-file-style: "bsd"