6 * Copyright 2012-2013, Olivier Berger & Institut Mines-Telecom
7 * Copyright 2013, Roland Mas
8 * Copyright 2021, Franck Villaume - TrivialDev
10 * This file is part of FusionForge. FusionForge is free software;
11 * you can redistribute it and/or modify it under the terms of the
12 * GNU General Public License as published by the Free Software
13 * Foundation; either version 2 of the Licence, or (at your option)
16 * FusionForge is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 // This Plugin publishes meta-data about the public projects hosted on the forge
27 // as RDF conforming to the ADMS.SW 1.0 specifications :
28 // https://joinup.ec.europa.eu/asset/adms_foss/release/release100
30 require_once 'common/include/TroveCat.class.php';
31 require_once 'common/frs/FRSFileType.class.php';
32 require_once $gfplugins.'admssw/common/RDFedFRSPackage.class.php' ;
33 require_once 'common/include/rdfutils.php';
34 include_once 'Graphite.php';
36 class admsswPlugin extends Plugin {
38 public static $PAGING_LIMIT = 50;
40 //var $trovecat_id_index; // cat_id to TroveCat instances
41 var $trovecat_id_to_shortname; // cat_id to shortname
42 var $trovecat_id_to_path; // cat_id to path
45 * @param number $id plugin identifier
47 function __construct($id=0) {
48 parent::__construct($id);
49 $this->name = "admssw";
50 $this->text = _("ADMS.SW"); // To show in the tabs, use...
52 _("This plugin provides ADMS.SW additions to the DOAP RDF documents for
53 projects on /projects URLs with content-negotiation
54 (application/rdf+xml).");
56 // The standard RDF namespaces that will be used in the plugin
58 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
59 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
60 'doap' => 'http://usefulinc.com/ns/doap#',
61 'dcterms' => 'http://purl.org/dc/terms/',
62 'admssw' => 'http://purl.org/adms/sw/',
63 'adms' => 'http://www.w3.org/ns/adms#',
64 'foaf' => 'http://xmlns.com/foaf/0.1/',
65 'schema' => 'http://schema.org/',
66 'rad' => 'http://www.w3.org/ns/rad#',
67 'ldp' => 'http://www.w3.org/ns/ldp#'
70 //$this->trovecat_id_index = array();
71 $this->trovecat_id_to_shortname = array();
72 $this->trovecat_id_to_path = array();
74 // Add the doaprdf plugin's namespaces
75 $doaprdfplugin = plugin_get_object ("doaprdf");
76 if ($doaprdfplugin == NULL)
78 // FIXME: constructor use of plugin_get_object
79 // requires 'doaprdf' to be listed before
80 // 'admssw' _in the plugins DB table_.
83 $ns = $doaprdfplugin->doapNameSpaces();
84 foreach($ns as $s => $u)
86 if (! in_array($u, $this->ns)) {
91 $this->_addHook("project_rdf_metadata"); // will provide some RDF metadata for the project's DOAP profile to 'doaprdf' plugin
92 $this->_addHook("alt_representations"); // declares a link to itself in the link+meta HTML headers of /projects and /softwaremap
93 $this->_addHook("script_accepted_types"); // supported alternate content-types (Accept HTTP header values)
94 $this->_addHook("content_negociated_projects_list"); // registers to be able to return content-negociated content for /projects/...
95 $this->_addHook("softwaremap_links"); // display additional submenu in the softwaremap tool
96 $this->_addHook("project_after_description"); // displays additional info in the project info widget
97 $this->_addHook("content_negociated_trove_list"); // generates the RDF document containing the trove categories as SKOS
98 $this->_addHook("content_negociated_frs_index"); // generates the public projects list/index as RDF
99 $this->_addHook("content_negociated_frs_download_file"); // generates the RDF meta-data about a FRS downloadable file
103 // General conneg related or other hook callbacks
107 * Declares itself as accepting RDF XML or Turtle on /projects and other scripts ...
109 * @param unknown_type $params
111 public function script_accepted_types (&$params) {
112 $script = $params['script'];
113 if ($script == 'projects_list' || $script == 'admssw_full' || $script == 'trove_list' || $script == 'frs_index' || $script == 'frs_download_file') {
114 $params['accepted_types'][] = 'application/rdf+xml';
115 $params['accepted_types'][] = 'text/turtle';
120 * Declares a link to itself in the link+meta HTML headers of /projects and /softwaremap
122 * @param unknown_type $params
124 public function alt_representations (&$params) {
125 $script_name = $params['script_name'];
126 $php_self = $params['php_self'];
127 if ($php_self == '/softwaremap/trove_list.php') {
128 $params['return'][] = '<link rel="alternate" type="application/rdf+xml" title="ADMS.SW RDF Data" href="'. util_make_url ("/plugins/admssw/trove.php") .'"/>';
129 $params['return'][] = '<link rel="alternate" type="text/turtle" title="ADMS.SW RDF Data" href="'. util_make_url ("/plugins/admssw/trove.php") .'"/>';
131 elseif ($script_name == '/softwaremap') {
132 $params['return'][] = '<link rel="alternate" type="application/rdf+xml" title="ADMS.SW RDF Data" href="'. util_make_url ("/projects") .'"/>';
133 $params['return'][] = '<link rel="alternate" type="text/turtle" title="ADMS.SW RDF Data" href="'. util_make_url ("/projects") .'"/>';
135 elseif($script_name == '/projects') {
136 $params['return'][] = '<link rel="alternate" type="application/rdf+xml" title="ADMS.SW RDF Data" href="'. util_make_url ($php_self) .'"/>';
137 $params['return'][] = '<link rel="alternate" type="text/turtle" title="ADMS.SW RDF Data" href="'. util_make_url ($php_self) .'"/>';
142 * Add a new link to the softwaremap submenu
144 * @param array $params
146 public function softwaremap_links (&$params) {
148 $params['TITLES'][] = _('ADMS.SW meta-data');
149 $params['URLS'][] = '/plugins/'. $this->name .'/index.php';
150 $params['ATTRS'][] = array('title' => _('ADMS.SW RDF meta-data about forge projects.'));
154 * Add a line in the project infos widget in the project home
156 * @param array $params
158 public function project_after_description (&$params) {
159 $group_id = $params['group_id'];
160 print '<br />'. sprintf( _('Preview <a href="%s">ADMS.SW meta-data</a> about the project'), util_make_url ('/plugins/'. $this->name .'/projectturtle.php?group_id='.$group_id));
168 * Returns namespaces used in ADMS.SW
170 * @return array the namespaces associative array
172 public function admsswNameSpaces() {
177 * Initialize Graphite graph's namespaces
179 private function graphSetAdmsswNameSpaces(&$graph) {
180 $ns = $this->admsswNameSpaces();
181 foreach($ns as $s => $u)
183 $graph->ns( $s, $u );
187 static function repositoryUri() {
188 return util_make_url ('/projects#repo');
192 // Project related methods and callbacks
196 * Provides an HTML preview of a project's ADMS.SW meta-data looking like turtle
198 * @param int $group_id
200 public function htmlPreviewProjectAsTurtle($group_id) {
204 $graph = new Graphite();
206 $this->graphSetAdmsswNameSpaces($graph);
208 $resourceindex = $this->addProjectResourceToGraph($graph, $group_id, $detailed);
210 return $graph->dump();
214 * Provides an ARC2 resource index of a project's ADMS.SW meta-data
216 * @param int $group_id
218 private function addProjectResourceToGraph(&$graph, $group_id, $detailed = false) {
220 // part of the work is done by the doaprdf plugin, which will in turn call us back (see project_rdf_metadata)
221 $doaprdfplugin = plugin_get_object ("doaprdf");
223 $ns = $this->admsswNameSpaces();
225 $resourceindex = $doaprdfplugin->getProjectResourceIndex($group_id, $ns, $detailed);
227 // update the namespaces if they happen to get updated in between
228 foreach($ns as $s => $u)
230 if (! in_array($u, $this->ns)) {
235 $count = $graph->addTriples( ARC2::getTriplesFromIndex($resourceindex) );
241 * Improves the DOAP description made by doaprdf (ARC2 resource) to add ADMS.SW meta-data for a project
243 * @param unknown_type $params
245 * This is a hook callback so part of the resource construction is made in the doaprdf plugin
247 public function project_rdf_metadata (&$params) {
249 # TODO : check that the passed in_Resource is indeed a doap:Project
250 $group_id = $params['group'];
252 // Update the prefixes by ADMS.SW ones
253 $new_prefixes = $this->admsswNameSpaces();
254 foreach($new_prefixes as $s => $u)
256 if (! isset($params['prefixes'][$u])) {
257 $params['prefixes'][$u] = $s;
262 if ($params['details'] == 'full') {
266 // The ARC2 RDF_Resource already initialized by doaprdf plugin
267 $res = $params['in_Resource'];
269 // we could save the type doap:Project in such case, as there's an equivalence, but not sure all consumers do reasoning
270 $types = array('doap:Project', 'admssw:SoftwareProject');
271 rdfutils_setPropToUri($res, 'rdf:type', $types);
273 // connect to FusionForge internals
274 $project = group_get_object($group_id);
276 // Handle project tags
278 if (forge_get_config('use_project_tags')) {
279 $tags_list = $project->getTags();
280 $tags = explode(', ',$tags_list);
281 // reuse the same as dcterms:subject until further specialization of adms.sw keywords
282 $res->setProp('rad:keyword', $tags);
285 $project_description = $project->getDescription();
286 if($project_description) {
287 // it seems that doap:description is not equivalent to dcterms:description, so repeat
288 $res->setProp('dcterms:description', $project_description);
291 // Handle trove categories
292 $trovecaturis=array('admssw:intendedAudience' => array(),
293 'admssw:locale' => array(),
294 'admssw:userInterfaceType' => array(),
295 'admssw:programmingLanguage' => array(),
296 'schema:operatingSystem' => array(),
297 'admssw:status' => array(),
298 'rad:theme' => array());
299 $trovecats = TroveCat::getProjectCats($group_id);
300 foreach($trovecats as $trovecat) {
301 $cat_id = $trovecat->getId();
302 if(!isset($this->trovecat_id_to_shortname[$cat_id])) {
303 $this->trovecat_id_to_shortname[$cat_id] = $trovecat->getShortName();
305 $idsfullpath = $trovecat->getIdsFullPath();
306 $folders_ids = explode(" :: ", $idsfullpath);
308 foreach ($folders_ids as $id) {
309 if (! isset($this->trovecat_id_to_shortname[$id])) {
310 $supercat = new TroveCat($id);
311 $this->trovecat_id_to_shortname[$id] = $supercat->getShortName();
313 $paths[] = $this->trovecat_id_to_shortname[$id];
315 $path=implode('/', $paths);
316 $this->trovecat_id_to_path[$cat_id] = $path;
317 $trovecaturi = util_make_url ('/softwaremap/trove/'.$path);
318 $rootcatid = $trovecat->getRootCatId();
319 $rootcatshortname = $this->trovecat_id_to_shortname[$rootcatid];
320 // This is a bit hackish
321 switch ($rootcatshortname) {
322 case 'developmentstatus':
323 $trovecaturis['admssw:status'][] = $trovecaturi;
326 $trovecaturis['admssw:intendedAudience'][] = $trovecaturi;
329 $trovecaturis['dcterms:license'][] = $trovecaturi;
332 $trovecaturis['admssw:locale'][] = $trovecaturi;
335 $trovecaturis['schema:operatingSystem'][] = $trovecaturi;
338 $trovecaturis['admssw:programmingLanguage'][] = $trovecaturi;
341 $trovecaturis['rad:theme'][] = $trovecaturi;
345 foreach ($trovecaturis as $prop => $uris) {
347 rdfutils_setPropToUri($res, $prop, $uris);
351 $res->setProp('rdfs:comment', "Generated with the doaprdf and admssw plugins of fusionforge");
353 rdfutils_setPropToUri($res, 'dcterms:isPartOf', admsswPlugin::repositoryUri());
355 // Handle project members
356 $admins = $project->getAdmins() ;
357 $members = $project->getUsers() ;
358 $contributors_uris = array();
359 foreach ($admins as $u) {
360 $contributor_uri = util_make_url_u($u->getUnixName());
361 $contributor_uri = rtrim($contributor_uri, '/');
362 $contributor_uri = $contributor_uri . '#person';
363 if (! in_array($contributor_uri, $contributors_uris) ) {
364 $contributors_uris[] = $contributor_uri;
367 foreach ($members as $u) {
368 $contributor_uri = util_make_url_u($u->getUnixName());
369 $contributor_uri = rtrim($contributor_uri, '/');
370 $contributor_uri = $contributor_uri . '#person';
371 if (! in_array($contributor_uri, $contributors_uris) ) {
372 $contributors_uris[] = $contributor_uri;
375 rdfutils_setPropToUri($res, 'schema:contributor', $contributors_uris);
377 // Handle FRS releases
378 $release_uris = array();
379 $frs_packages = get_rdfed_frs_packages($project);
380 foreach ($frs_packages as $frs_package) {
381 //print_r($frs_package);
383 if($frs_package->isPublic() && $frs_package->getStatus() == 1) {
384 $package_name = $frs_package->getFileName();
386 $frs_releases = $frs_package->getReleases();
387 foreach ($frs_releases as $frs_release) {
388 if( $frs_release->getStatus() == 1 ) {
389 //print_r($frs_release);
390 $release_uris[] = $frs_release->getUri();
395 if(count($release_uris)) {
396 rdfutils_setPropToUri($res, 'doap:release', $release_uris);
398 // The releases aren't discoverable by follow your nose yet, so add the proper document/script URL to use
399 rdfutils_setPropToUri($res, 'rdfs:seeAlso', util_make_url ('/frs/?group_id='.$group_id));
401 $params['out_Resources'][] = $res;
404 $graph = new Graphite();
405 $this->graphSetAdmsswNameSpaces($graph);
407 $this->addProjectFrsResourcesToGraph($graph, $group_id);
409 $subjects = $graph->allSubjects();
410 foreach ($subjects as $subject) {
411 $resource = $graph->resource( $subject );
412 $triples = $resource->toArcTriples();
414 $index = ARC2::getSimpleIndex($triples, false);
416 $res = ARC2::getResource();
417 $res->setIndex($index);
419 $params['out_Resources'][] = $res;
428 // Project list / SoftwareRepository related methods
432 * Returns the number of projects in a project index
434 public function getProjectListSize() {
435 // same as for trove's full list
436 $projects = group_get_public_active_projects_asc();
437 return count($projects);
441 * Provides a Graphite graph for resource(s) representing the ADMS.SW SoftwareRepository
443 * @param string URI of the document to use
444 * @param bool are projects to be fully described or just a URI of their resource
445 * @param $chunk number of the chunk to be returned in case of paging
446 * @param $chunksize size of chunks in case of paging
448 public function getProjectListResourcesGraph($documenturi, $detailed=false, $chunk=null, $chunksize=null) {
450 // Construct an ARC2_Resource containing the project's RDF (DOAP) description
451 $ns = $this->admsswNameSpaces();
457 $res = ARC2::getResource($conf);
458 $res->setURI( admsswPlugin::repositoryUri() );
460 // $res->setRel('rdf:type', 'admssw:SoftwareRepository');
461 rdfutils_setPropToUri($res, 'rdf:type', 'admssw:SoftwareRepository');
463 //$res->setProp('doap:name', $projectname);
464 rdfutils_setPropToUri($res, 'adms:accessURL', util_make_url ("/softwaremap/") );
465 $forge_name = forge_get_config ('forge_name');
466 $ff = new FusionForge();
467 $res->setProp('dcterms:description', 'Public projects in the '. $ff->software_name .' Software Map on '. $forge_name );
468 $res->setProp('rdfs:label', $forge_name .' public projects');
469 $res->setProp('adms:supportedSchema', 'ADMS.SW v1.0');
471 // same as for trove's full list
472 $projects = group_get_public_active_projects_asc();
474 if ( isset($chunk) && isset($chunksize) ) {
475 // TODO : do some checks on $chunk $chunksize values
476 // if ( ($chunk < 1) && ($chunksize >= 1) ) {
479 $projects_chunks = array_chunk($projects, $chunksize);
480 $projects = $projects_chunks[$chunk-1];
483 $proj_uris = array();
484 foreach ($projects as $row_grp) {
485 $proj_uri = util_make_url_g(strtolower($row_grp['unix_group_name'])).'#project';
486 $proj_uris[] = $proj_uri;
488 if(count($proj_uris)) {
489 rdfutils_setPropToUri($res, 'dcterms:hasPart', $proj_uris);
492 $graph = new Graphite();
493 $this->graphSetAdmsswNameSpaces($graph);
495 $count = $graph->addTriples( ARC2::getTriplesFromIndex($res->index) );
497 // if needed, provide also full details about the projects
498 foreach ($projects as $row_grp) {
499 $group_id = $row_grp['group_id'];
500 //$proj_uri = util_make_url_g(strtolower($row_grp['unix_group_name']));
501 $count = $this->addProjectResourceToGraph($graph, $row_grp['group_id'], $detailed);
504 $this->graphSetAdmsswNameSpaces($graph);
506 // The document the document itself
507 $res = ARC2::getResource($conf);
508 $res->setURI( $documenturi );
509 rdfutils_setPropToUri($res, 'rdf:type', 'foaf:Document');
510 rdfutils_setPropToUri($res, 'foaf:primaryTopic', admsswPlugin::repositoryUri() );
511 rdfutils_setPropToXSDdateTime($res, 'dcterms:created', date('c'));
512 $res->setProp('dcterms:title', "ADMS.SW full dump" );
514 $count = $graph->addTriples( ARC2::getTriplesFromIndex($res->index) );
520 * Returns the size of the pages for paged documents (project indexes or full projects dump)
522 public function getPagingLimit() {
523 return self::$PAGING_LIMIT;
527 * Process the paging parameters and eventually redirect, ala LDP
529 * When there are too many projects to be displayed, it will redirect to the first page : ?page=1
530 * This can be overriden with the ?allatonce parameter
532 public function process_paging_params_or_redirect($projectsnum, $pl) {
534 $p = getIntFromRequest('page', 0);
536 if ( null !== getStringFromRequest('allatonce', null)) {
537 $pl = $projectsnum + 1;
541 // force paging if too many projects
542 if ( ($projectsnum > $pl) && ! ($p > 0) ) {
543 header("Location: ?page=1");
544 header($_SERVER["SERVER_PROTOCOL"]." 303 See Other",true,303);
548 // if paging is requested
550 $maxpage = ceil($projectsnum / $pl);
552 header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found",true,404);
553 printf("Page %d requested is beyond the maximum %d !", $p, $maxpage);
562 * Provides either an HTML preview looking like turtle, or plain RDF of the ADMS.SW SoftwareRepository meta-data
564 * @param string URL of the RDF document
565 * @param string expected content type for the document
566 * @param int page number. If null, means no paging but full document
567 * @param int page length : how many projects per page
568 * @param bool if has to provide full details about projects
569 * @param string URL of the HTML script if different than the RDF document
571 public function getProjectsListDisplay($documenturi, $content_type, $p, $pl, $detailed=false, $scripturl=false) {
576 $scripturl = $documenturi;
582 // if paging is requested
586 $pageuri = $documenturi . '?page='. (string)$p;
589 $projectsnum = $this->getProjectListSize();
591 // process as in content_negociated_projects_list but with full details
592 $graph = $this->getProjectListResourcesGraph($documenturi, $detailed, $chunk, $chunksize);
595 if($content_type != 'text/html') {
598 $ns = $this->admsswNameSpaces();
603 $res = ARC2::getResource($conf);
604 $res->setURI( $pageuri );
605 rdfutils_setPropToUri($res, 'rdf:type', 'ldp:Page');
607 if( $p < ceil($projectsnum / $pl) ) {
608 $nextpageuri = $documenturi . '?page=' . (string) ($p + 1);
609 rdfutils_setPropToUri($res, 'ldp:nextPage', $nextpageuri);
612 rdfutils_setPropToUri($res, 'ldp:nextPage', 'rdf:nil');
614 rdfutils_setPropToUri($res, 'ldp:pageOf', $documenturi);
616 $count = $graph->addTriples( ARC2::getTriplesFromIndex($res->index) );
619 // We can support only RDF as RDF+XML or Turtle
620 if ($content_type == 'text/turtle' || $content_type == 'application/rdf+xml') {
621 if ($content_type == 'text/turtle') {
622 $doc = $graph->serialize($serializer="Turtle")."\n";
624 if ($content_type == 'application/rdf+xml') {
625 $doc = $graph->serialize()."\n";
629 header('HTTP/1.1 406 Not Acceptable',true,406);
630 print $graph->dumpText();
636 $doc = '<p>'. _('The following is a preview of (machine-readable) RDF meta-data, in Turtle format (see at the bottom for more details)') .'<br />';
638 $html_limit = '<span style="text-align:center;font-size:smaller">';
639 $html_limit .= sprintf(_('<strong>%d</strong> projects in result set.'), $projectsnum);
640 // only display pages stuff if there is more to display
641 if ($projectsnum > $pl) {
642 $html_limit .= html_trove_limit_navigation_box($scripturl, $projectsnum, $pl, $p);
644 $html_limit .= '</span>';
648 $doc .= $graph->dump();
650 $doc .= _('To access this RDF document, you may use, for instance:');
652 $doc .= '<kbd>$ curl -L -H "Accept: text/turtle" '. $documenturi .'</kbd><br />';
654 $doc .= _('This may redirect to several pages documents in case of too big number of results (observing the LDP paging specifications).');
655 $doc .= '<br /><br />';
657 $doc .= _('Alternatively, if you are sure you want the full dump in one single document, use:');
659 $doc .= '<kbd>$ curl -H "Accept: text/turtle" "'. $documenturi .'?allatonce"</kbd>';
666 * Outputs the public projects list as ADMS.SW for /projects
668 * @param unknown_type $params
670 * This has a counterpart in /plugins/admssw/projectsturtle.php which previews the Turtle as HTML
672 public function content_negociated_projects_list (&$params) {
674 $accept = $params['accept'];
676 // we are asked for RDF either as RDF+XML or Turtle
677 if($accept == 'application/rdf+xml' || $accept == 'text/turtle') {
679 // We will return RDF
680 $params['content_type'] = $accept;
682 $documenturi = util_make_url ("/projects");
685 $pl = admsswPlugin::$PAGING_LIMIT;
687 $projectsnum = $this->getProjectListSize();
689 $p = $this->process_paging_params_or_redirect($projectsnum, $pl);
691 $doc = $this->getProjectsListDisplay($documenturi, $accept, $p, $pl);
693 $params['content'] = $doc . "\n";
699 // Trove related methods
703 * Provides a Graphite graph for resource(s) representing the trove categories as SKOS concepts
706 private function getTroveListResourcesGraph() {
708 // Construct an ARC2_Resource containing the project's RDF (DOAP) description
710 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
711 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
712 'skos' => 'http://www.w3.org/2004/02/skos/core#'
720 $graph = new Graphite();
721 $this->graphSetAdmsswNameSpaces($graph);
723 $rootcats = TroveCat::getAllRoots();
725 foreach($rootcats as $rootcat) {
727 // First the ConceptScheme itself
729 $conceptschemeres = ARC2::getResource($conf);
731 $scheme_shortname = $rootcat->getShortName();
732 $conceptscheme_uri = util_make_url ('/softwaremap/trove/'.$scheme_shortname);
733 $conceptschemeres->setURI( $conceptscheme_uri );
735 // $res->setRel('rdf:type', 'doap:Project');
736 rdfutils_setPropToUri($conceptschemeres, 'rdf:type', 'skos:ConceptScheme');
738 $conceptschemeres->setProp('skos:prefLabel', $rootcat->getFullName());
739 $conceptschemeres->setProp('skos:definition', $rootcat->getDescription());
741 $count = $graph->addTriples( ARC2::getTriplesFromIndex($conceptschemeres->index) );
744 $subcats = $rootcat->listSubTree();
746 // memorize a few indexes
748 foreach($subcats as $subcat) {
749 $cat_id = $subcat->getId();
750 //$this->trovecat_id_index[$cat_id] = &$subcat;
752 $this->trovecat_id_to_shortname[$cat_id] = $subcat->getShortName();
755 foreach($subcats as $subcat) {
756 $cat_id = $subcat->getId();
758 $idsfullpath = $subcat->getIdsFullPath();
760 $folders_ids = explode(" :: ", $idsfullpath);
763 foreach ($folders_ids as $id) {
764 if (isset($this->trovecat_id_to_shortname[$id])) {
765 $paths[] = $this->trovecat_id_to_shortname[$id];
768 $path=implode('/', $paths);
770 $this->trovecat_id_to_path[$cat_id] = $path;
773 // Now, for all Concepts in this ConceptScheme
775 foreach($subcats as $subcat) {
776 $conceptres = ARC2::getResource($conf);
778 $path = $this->trovecat_id_to_path[$subcat->getId()];
779 $conceptres->setURI( util_make_url ('/softwaremap/trove/'.$scheme_shortname.'/'.$path) );
781 // $res->setRel('rdf:type', 'doap:Project');
782 rdfutils_setPropToUri($conceptres, 'rdf:type', 'skos:Concept');
784 rdfutils_setPropToUri($conceptres, 'skos:inScheme', $conceptscheme_uri);
786 $conceptres->setProp('skos:prefLabel', $subcat->getFullName());
787 $conceptres->setProp('skos:definition', $subcat->getDescription());
789 $parentid = $subcat->getParentId();
790 $rootparentid = $subcat->getRootCatId();
792 if ($parentid != $rootparentid) {
793 $parentpath = $this->trovecat_id_to_path[$parentid];
794 rdfutils_setPropToUri($conceptres, 'skos:broader', util_make_url ('/softwaremap/trove/'.$scheme_shortname.'/'.$parentpath) );
797 $count = $graph->addTriples( ARC2::getTriplesFromIndex($conceptres->index) );
806 * Provides an HTML preview of the trove categories as SKOS looking like turtle
809 public function htmlPreviewTroveCatsAsTurtle() {
810 $graph = $this->getTroveListResourcesGraph();
812 return $graph->dump();
816 * Outputs the trove categories as SKOS
818 * @param unknown_type $params
820 public function content_negociated_trove_list (&$params) {
822 $accept = $params['accept'];
824 // we are asked for RDF either as RDF+XML or Turtle
825 if($accept == 'application/rdf+xml' || $accept == 'text/turtle') {
828 // We will return RDF
829 $params['content_type'] = $accept;
831 $graph = $this->getTroveListResourcesGraph();
833 if ($accept == 'text/turtle') {
834 $doc = $graph->serialize($serializer="Turtle");
836 if ($accept == 'application/rdf+xml') {
837 $doc = $graph->serialize();
840 $params['content'] = $doc . "\n";
847 // FRS related methods
851 * Add RDF resources to a Graphite graph for the File Release system
853 * @param Graphite graph to be updated
854 * @param int group id
855 * @param int optional release id
857 private function addProjectFrsResourcesToGraph(&$graph, $group_id, $release_id = false) {
859 $group = group_get_object($group_id);
861 // if we are passed a release ID, then only process that particular release
864 $frs_release = rdfed_frsrelease_get_object($release_id);
866 // Don't produce RDF for hidden releases
867 if( $frs_release->getStatus() == 1 ) {
868 $frs_package = $frs_release->getFRSPackage();
870 // Only produce RDF for releases of public and not hidden packages
871 if ($frs_package->isPublic() && $frs_package->getStatus() == 1) {
873 $frs_release->saveToGraph($graph);
879 // then produce RDF for all the project's packages
880 $frs_packages = get_rdfed_frs_packages($group);
882 foreach($frs_packages as $frs_package) {
883 // well actually, only for public and not hidden packages
884 if ($frs_package->isPublic() && $frs_package->getStatus() == 1) {
886 $frs_package->saveToGraph($graph);
895 * Outputs the public projects releases as ADMS.SW for /frs
897 * @param unknown_type $params
899 public function content_negociated_frs_index (&$params) {
901 $accept = $params['accept'];
903 // we are asked for RDF either as RDF+XML or Turtle
904 if($accept == 'application/rdf+xml' || $accept == 'text/turtle') {
907 // We will return RDF
908 $params['content_type'] = $accept;
910 $group_id = $params['group_id'];
911 $release_id = $params['release_id'];
913 $graph = new Graphite();
914 $this->graphSetAdmsswNameSpaces($graph);
916 $this->addProjectFrsResourcesToGraph($graph, $group_id, $release_id);
918 if ($accept == 'text/turtle') {
919 $doc = $graph->serialize($serializer="Turtle");
921 if ($accept == 'application/rdf+xml') {
922 $doc = $graph->serialize();
925 $params['content'] = $doc . "\n";
931 * Outputs the public downloadable files as ADMS.SW SoftwarePackages for /frs/download.php...
933 * @param unknown_type $params
935 public function content_negociated_frs_download_file (&$params) {
937 $accept = $params['accept'];
939 // we are asked for RDF either as RDF+XML or Turtle
940 if($accept == 'application/rdf+xml' || $accept == 'text/turtle') {
942 // We will return RDF
943 $params['content_type'] = $accept;
945 $file_id = $params['file_id'];
947 $frs_file = rdfed_frsfile_get_object($file_id);
949 session_redirect404();
952 $frs_release = $frs_file->getFRSRelease();
953 $frs_package = $frs_release->getFRSPackage();
954 $group = $frs_package->getGroup();
956 $graph = new Graphite();
957 $this->graphSetAdmsswNameSpaces($graph);
959 // We only accept files in public and non-hidden project's packages
960 if ($frs_package->isPublic() && $frs_package->getStatus() == 1) {
961 $frs_file->saveToGraph($graph);
964 if ($accept == 'text/turtle') {
965 $doc = $graph->serialize($serializer="Turtle");
967 if ($accept == 'application/rdf+xml') {
968 $doc = $graph->serialize();
971 $params['content'] = $doc . "\n";
979 // c-file-style: "bsd"