<?php
/**
 * api: php
 * title: rebuild composer.lock/json
 * description: Traverse 𝑣𝑒𝑛𝑑𝑜𝑟⁄⁎⁄⁎⁄ dirs, extract →extra→lock data, reassemble composer state
 * version: 0.1
 * type: cli
 *
 * Used by php-composer-vnd-pkg.deb packages to reconstruct composer
 * autoloader for system-managed /usr/share/php/vendor/ packages.
 *
 */

# prepare array assembling
$composer_json = array("require" => array());
$composer_lock = array("packages" => array()); #file_exists("composer.lock") ? json_decode(file_get_contents("composer.lock"), TRUE) ? array();

# traverse existing vendor packages
foreach (array_filter(glob("vendor/*/*"), "is_dir") as $pkg_dir) {

    $name = trim(strstr($pkg_dir, "/"), "/");
    $pkg_json_fn = findutil_r($pkg_dir, "composer.json");
    $json = array();

    # read in data
    if (!empty($pkg_json_fn) and file_exists($pkg_json_fn)) {
        $json = json_decode(file_get_contents($pkg_json_fn), TRUE);
    }

    # add to lists
    $composer_lock["packages"][$name] = array_merge(
        array("version" => "0.0.0", "name" => $name),
        $json,
        isset($json["extra"]["lock"]) ? $json["extra"]["lock"] : array("version_normalized" => "0.0.0.0")
    );
    unset($composer_lock["packages"][$name]["extra"]["lock"]);
    # stub
    $composer_json["require"][$name] = "*";  // sufficient for our use case

}

# store
#var_dump($composer_json);
merge_json("composer.json", $composer_json, array("require"=>array()) );
#var_dump($composer_lock);
merge_json("composer.lock", $composer_lock, array("packages"=>array(), "_readme"=>"@generated", "packages-dev"=>array(), "aliases"=>array(), "minimum-stability"=>"stable", "stability-flags"=>array(), "prefer-stable"=>false, "platform"=>array(), "platform-dev"=>array()) );
# composer needs installed.json as well
if (!file_exists("vendor/composer")) {
    mkdir("vendor/composer");
}
file_put_contents("vendor/composer/installed.json", json_encode(array_values($composer_lock["packages"]), JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));


/**
 * Merge all the things.
 * (Collected composer.json/lock data into/if existing scripts.)
 *
 */
function merge_json($fn, $add, $stub) {

    # read existing
    if (file_exists($fn)) {
       $data = json_decode(file_get_contents($fn), TRUE) or $data = array();
    }
    else {
       $data = array();
    }
    
    # combine in stub
    $data = array_merge($stub, $data);
    
    # overwrite with collected entries, new data takes precedence, just two levels
    foreach (array("require", "packages") as $field) {
        if (isset($add[$field])) {
           if (is_scalar($add[$field])) {
               $data[$field] = $add[$field];
           }
           else foreach ($add[$field] as $key=>$val) {
               $data[$field][$key] = $val;
           }
        }
    }
    
    # store back
    file_put_contents($fn, json_encode($data, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));
}


/**
 * Scan subdirs until $fn found.
 *
 */
function findutil_r($dir, $fn) {
    # read dir, check for file
    if (in_array("$dir/$fn", $glob = glob("$dir/*"))) {
        return "$dir/$fn";
    }
    # just submerge into first existing subdir
    elseif ($glob = array_filter($glob, "is_dir")) {
        foreach ($glob as $dir) {
            return findutil_r($dir, $fn);
        }
    }
}

