Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

Revision 3233d06e85a9aa04fc362201f8154552d6b5b308 authored by Ramy-Badr-Ahmed on 24 July 2024, 16:59:37 UTC, committed by GitHub on 24 July 2024, 16:59:37 UTC
Merge pull request #1 from physikerwelt/patch-1
Fix typo in SWH_TOKEN_PROD
2 parent s 8d1239c + 4531537
  • Files
  • Changes
  • 1c4ca38
  • /
  • Module
  • /
  • DAGModel
  • /
  • GraphHopping.php
Raw File Download
Permalinks

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • revision
  • directory
  • content
revision badge
swh:1:rev:3233d06e85a9aa04fc362201f8154552d6b5b308
directory badge Iframe embedding
swh:1:dir:a199ee1a8be7a01922ddd42c0c6f77447fbbde74
content badge Iframe embedding
swh:1:cnt:f91c8c8f53e6d291402f376a6e6d41a8f1a46cfa
Citations

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • revision
  • directory
  • content
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
GraphHopping.php
<?php

/**
 * @Author: Ramy-Badr-Ahmed
 * @Desc: SWH API Client
 * @Repo: https://github.com/Ramy-Badr-Ahmed/swh-client
 */

namespace Module\DAGModel;

use Exception;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Collection;
use Module\Globals\Formatting;
use Module\Globals\Helper;
use Module\HTTPConnector\HTTPClient;
use Module\HTTPConnector\SyncHTTP;
use stdClass;
use Throwable;

abstract class GraphHopping
{
    public const SUPPORTED_OPTIONS = ["stringType", "withHeaders"];

    private const EXISTS = 'Exists in SWH';


    /**
     * @param string $snapshotID
     * @param ...$flags
     * @return iterable|Collection|stdClass|Throwable
     */
    public static function getFullSnapshot(string $snapshotID, ...$flags): Iterable|Collection|stdClass|Throwable
    {
        return self::buildFullSnapshot($snapshotID, ...$flags);
    }


    /**
     * @param string $snapshotID
     * @param string|NULL $branchesFrom
     * @param ...$flags
     * @return iterable|Collection|stdClass|Throwable
     */
    private static function buildFullSnapshot(string $snapshotID, string $branchesFrom = NULL, ...$flags): Iterable|Collection|stdClass|Throwable
    {
        $appendBranches2ResponseSnp["branches"]=[];
        $appendBranches2ResponseSnp["next_branch"] = null;

        $responseType = HTTPClient::$responseType;

        try{
            Helper::validateOptions($flags);

            $snapshotID = Formatting::extractHex($snapshotID, Formatting::SWH_SNAPSHOT);

            $append2Url= isset($branchesFrom)
                ? collect($snapshotID."/?branches_from=".$branchesFrom)
                : collect($snapshotID);

            $responseSnp = SyncHTTP::call("GET", 'snapshot', $append2Url, ...$flags);

            if($responseSnp instanceof Throwable){
                return $responseSnp;
            }
            $responseSnpJson = $responseSnp->json();

        }catch (RequestException $e){
            HTTPClient::addErrors($e->getCode()." : " . match ($e->getCode()){
                    400 => "An invalid Snapshot identifier: $snapshotID",
                    404 => "Requested Snapshot was not found in SWH",
                    default => $e->response->json()['reason'] ?? $e->response->body()
                });
            return $e;
        }catch (Exception $e){
            HTTPClient::addErrors($e->getCode().": ".$e->getMessage());
            return $e;
        }

        if(isset($responseSnp["next_branch"])){
            HTTPClient::setOptions(responseType: HTTPClient::RESPONSE_TYPE_ARRAY);
            $appendBranches2ResponseSnp = self::buildFullSnapshot($snapshotID, $responseSnpJson["next_branch"]);
        }

        $responseSnpJson["branches"] = array_merge($responseSnpJson["branches"], $appendBranches2ResponseSnp["branches"]);
        $responseSnpJson["next_branch"] = $appendBranches2ResponseSnp["next_branch"];

        $responseSnpCast = Formatting::reCastTo($responseSnpJson, $responseType);
        HTTPClient::setOptions(responseType: $responseType);


        return $flags['withHeaders'] ?? false
            ? collect(["response" => $responseSnpCast, "headers" => $responseSnp->headers()])
            : $responseSnpCast;
    }

    /**
     * @param string $releaseID
     * @param ...$flags
     * @return iterable|Collection|stdClass|Throwable
     */
    public static function getFullRelease(string $releaseID, ...$flags): Iterable|Collection|stdClass|Throwable
    {
        $responseType = HTTPClient::$responseType;

        try{
            Helper::validateOptions($flags);

            $releaseID = Formatting::extractHex($releaseID, Formatting::SWH_RELEASE);

            $responseRel = SyncHTTP::call("GET", 'release', collect($releaseID), ...$flags);

            if($responseRel instanceof Throwable){
                return $responseRel;
            }

            return $flags['withHeaders'] ?? false
                ? collect(["response" => $responseRel->$responseType(), "headers" => $responseRel->headers()])
                : $responseRel->$responseType();

        }catch (RequestException $e){
            HTTPClient::addErrors($e->getCode()." : " . match ($e->getCode()){
                    400 => "An invalid Release identifier: $releaseID",
                    404 => "Requested Release was not found in SWH",
                    default => $e->response->json()['reason'] ?? $e->response->body()
                });
            return $e;
        }catch (Exception $e){
            HTTPClient::addErrors($e->getCode().": ".$e->getMessage());
            return $e;
        }
    }

    /**
     * @param string $revisionID
     * @param ...$flags
     * @return iterable|Collection|stdClass|Throwable
     */
    public static function getFullRevision(string $revisionID, ...$flags): Iterable|Collection|stdClass|Throwable
    {
        $responseType = HTTPClient::$responseType;

        try{
            Helper::validateOptions($flags);

            $revisionID = Formatting::extractHex($revisionID, Formatting::SWH_REVISION);

            $responseRev = SyncHTTP::call("GET", 'revision', collect($revisionID), ...$flags);

            if($responseRev instanceof Throwable){
                return $responseRev;
            }

            return $flags['withHeaders'] ?? false
                ? collect(["response" => $responseRev->$responseType(), "headers" => $responseRev->headers()])
                : $responseRev->$responseType();

        }catch (RequestException $e){
            HTTPClient::addErrors($e->getCode()." : " . match ($e->getCode()){
                    400 => "An invalid Revision identifier: $revisionID",
                    404 => "Requested Revision was not found in SWH",
                    default => $e->response->json()['reason'] ?? $e->response->body()
                });
            return $e;
        }catch (Exception $e){
            HTTPClient::addErrors($e->getCode().": ".$e->getMessage());
            return $e;
        }
    }

    /**
     * @param string $directoryID
     * @param ...$flags
     * @return iterable|Collection|Throwable
     */
    public static function getFullDirectory(string $directoryID, ...$flags): Iterable|Collection|Throwable
    {
        $responseType = HTTPClient::$responseType;

        try{
            Helper::validateOptions($flags);

            $directoryID = Formatting::extractHex($directoryID, Formatting::SWH_DIRECTORY);

            $responseDir = SyncHTTP::call("GET", 'directory', collect($directoryID), ...$flags);

            if($responseDir instanceof Throwable){
                return $responseDir;
            }

            return $flags['withHeaders'] ?? false
                ? collect(["response" => $responseDir->$responseType(), "headers" => $responseDir->headers()])
                : $responseDir->$responseType();

        }catch (RequestException $e){
            HTTPClient::addErrors($e->getCode()." : " . match ($e->getCode()){
                    400 => "An invalid Directory identifier: $directoryID",
                    404 => "Requested Directory was not found in SWH",
                    default => $e->response->json()['reason'] ?? $e->response->body()
                });
            return $e;
        }catch (Exception $e){
            HTTPClient::addErrors($e->getCode().": ".$e->getMessage());
            return $e;
        }
    }

    /**
     * @param string $contentID
     * @param ...$flags
     * @return iterable|Collection|stdClass|Throwable
     */
    public static function getFullContent(string $contentID, ...$flags): Iterable|Collection|stdClass|Throwable
    {
        $responseType = HTTPClient::$responseType;

        try{
            Helper::validateOptions($flags);

            $contentID = Formatting::extractHex($contentID, Formatting::SWH_CONTENT);

            $responseCnt = SyncHTTP::call("GET", 'content', collect($contentID), ...$flags);

            if($responseCnt instanceof Throwable){
                return $responseCnt;
            }

            return $flags['withHeaders'] ?? false
                ? collect(["response" => $responseCnt->$responseType(), "headers" => $responseCnt->headers()])
                : $responseCnt->$responseType();

        }catch (RequestException $e) {
            HTTPClient::addErrors($e->getCode() . " : " . match ($e->getCode()) {
                    400 => "An invalid Content identifier: $contentID",
                    404 => "Requested Content was not found in SWH",
                    default => $e->response->json()['reason'] ?? $e->response->body()
                });
            return $e;
        }catch (Exception $e){
            HTTPClient::addErrors($e->getCode().": ".$e->getMessage());
            return $e;
        }
    }


    /**
     * @param string $snapshotID
     * @param ...$flags
     * @return String|bool|Throwable
     */
    public static function snapshotExists(string $snapshotID, ...$flags): String|Bool|Throwable
    {
        try{
            Helper::validateOptions($flags);

            $snapshotID = Formatting::extractHex($snapshotID, Formatting::SWH_SNAPSHOT);

            $responseSnp = SyncHTTP::call("HEAD", 'snapshot', collect($snapshotID), [], ...$flags);

            if($responseSnp instanceof Throwable){
                return $responseSnp;
            }

            return $flags['stringType'] ?? false
                ? Formatting::formatSwhIDs('snapshot', $snapshotID)." --> " .self::EXISTS
                : boolval($responseSnp->status());

        }catch (RequestException $e){
            HTTPClient::addErrors($e->getCode()." : " . match ($e->getCode()){
                    400 => "An invalid Snapshot identifier: $snapshotID",
                    404 => "Requested Snapshot was not found in SWH",
                    default => $e->getMessage()
                });
            return $e;
        }catch(Exception $e){
            HTTPClient::addErrors($e->getCode().": ".$e->getMessage());
            return $e;
        }
    }

    /**
     * @param string $releaseID
     * @param ...$flags
     * @return String|bool|Throwable
     */
    public static function releaseExists(string $releaseID, ...$flags): String|Bool|Throwable
    {
        try{
            Helper::validateOptions($flags);

            $releaseID = Formatting::extractHex($releaseID, Formatting::SWH_RELEASE);

            $responseRel = SyncHTTP::call("HEAD",'release', collect($releaseID),...$flags);

            if($responseRel instanceof Throwable){
                return $responseRel;
            }

            return $flags['stringType'] ?? false
                ? Formatting::formatSwhIDs('release', $releaseID)." --> ".self::EXISTS
                : boolval($responseRel->status());

        }catch(RequestException $e){
            HTTPClient::addErrors($e->getCode()." : " . match ($e->getCode()){
                    400 => "An invalid Release sha1_git: $releaseID",
                    404 => "Requested Release was not found in SWH",
                    default => $e->getMessage()
                });
            return $e;
        }catch(Exception $e){
            HTTPClient::addErrors($e->getCode().": ".$e->getMessage());
            return $e;
        }
    }

    /**
     * @param string $revisionID
     * @param ...$flags
     * @return String|bool|Throwable
     */
    public static function revisionExists(string $revisionID, ...$flags): String|Bool|Throwable
    {
        try{
            Helper::validateOptions($flags);

            $revisionID = Formatting::extractHex($revisionID, Formatting::SWH_REVISION);

            $responseRev = SyncHTTP::call("HEAD",'revision', collect($revisionID), ...$flags);

            if($responseRev instanceof Throwable){
                return $responseRev;
            }

            return $flags['stringType'] ?? false
                ? Formatting::formatSwhIDs('revision', $revisionID)." --> ".self::EXISTS
                : boolval($responseRev->status());

        }catch(RequestException $e) {
            HTTPClient::addErrors($e->getCode() . " : " . match ($e->getCode()) {
                    400 => "An invalid Revision sha1_git: $revisionID",
                    404 => "Requested Revision was not found in SWH",
                    default => $e->getMessage()
                });
            return $e;
        }catch(Exception $e){
            HTTPClient::addErrors($e->getCode().": ".$e->getMessage());
            return $e;
        }
    }

    /**
     * @param string $directoryID
     * @param ...$flags
     * @return String|bool|Throwable
     */
    public static function directoryExists(string $directoryID, ...$flags): String|Bool|Throwable
    {
        try{
            Helper::validateOptions($flags);

            $directoryID = Formatting::extractHex($directoryID, Formatting::SWH_DIRECTORY);

            $responseDir = SyncHTTP::call("HEAD",'directory', collect($directoryID), ...$flags);

            if($responseDir instanceof Throwable){
                return $responseDir;
            }

            return $flags['stringType'] ?? false
                ? Formatting::formatSwhIDs('directory', $directoryID)." --> ".self::EXISTS
                : boolval($responseDir->status());

        }catch(RequestException $e) {
            HTTPClient::addErrors($e->getCode() . " : " . match ($e->getCode()) {
                    400 => "An invalid Directory sha1_git: $directoryID",
                    404 => "Requested Directory was not found in SWH",
                    default => $e->getMessage()
                });
            return $e;
        }catch(Exception $e){
            HTTPClient::addErrors($e->getCode().": ".$e->getMessage());
            return $e;
        }
    }

    /**
     * @param string $contentID
     * @param ...$flags
     * @return String|bool|Throwable
     */
    public static function contentExists(string $contentID, ...$flags): String|Bool|Throwable
    {
        try{
            Helper::validateOptions($flags);

            $contentID = Formatting::extractHex($contentID, Formatting::SWH_CONTENT);

            $responseCnt = SyncHTTP::call("HEAD",'content', collect($contentID),...$flags);

            if($responseCnt instanceof Throwable){
                return $responseCnt;
            }

            return $flags['stringType'] ?? false
                ? Formatting::formatSwhIDs('content', $contentID)." --> ".self::EXISTS
                : boolval($responseCnt->status());

        }catch(RequestException $e) {
            HTTPClient::addErrors($e->getCode() . " : " . match ($e->getCode()) {
                    400 => "An invalid Content sha1_git: $contentID",
                    404 => "Requested Content was not found in SWH",
                    default => $e->getMessage()
                });
            return $e;
        }catch(Exception $e){
            HTTPClient::addErrors($e->getCode().": ".$e->getMessage());
            return $e;
        }
    }

}
The diff you're trying to view is too large. Only the first 1000 changed files have been loaded.
Showing with 0 additions and 0 deletions (0 / 0 diffs computed)
swh spinner

Computing file changes ...

back to top

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Contact— JavaScript license information— Web API