php 拓展包,依赖包,可视化

php 解析composer依赖关系,生成视图

php 解析composer依赖关系,生成视图
use crud\models\Rely;
$model = new Rely();
$model->vendorDir = '/vendor');
//$model->env =false;
$model->baseComposerJson = "/composer.json";
$model->baseComposerLock = "/composer.lock";
echo $model-> renderHtml();
<?php


namespace crud\models;


use yii\base\Model;

/**
 * 生成composer 依赖关系图
 * @package crud\models
 */
class Rely extends Model
{

    public $vendorDir = '';
    public $baseComposerJson = '';
    public $baseComposerLock='';
    public $env = true;
    public $_require=[];
    public $projectName="shiguangxiaotou/wordpress";
    public $data =[
        "nodes" => [
//            [
//                "id" => "0",
//                "name" => "shiguangxiaotou/wordpress",
//                "symbolSize" => 20,
//                "value" => "1.3.0",
//                "category" => 0
//            ],
        ],
        "links" => [
//            "source" => $nodeId,
//            "target" => $fatherId
        ],
        "categories" => [
//            ['name'=>'adads']
        ]
    ];

    /**
     * 获取已安装拓展包已安装版本
     * @param $projectName
     * @return mixed|string
     */
    public function getVersion($projectName){
        $str_json = file_get_contents($this->baseComposerLock);
        $arr = json_decode($str_json,true);
        $packages = ($this->env) ? $arr['packages']:$arr['packages-dev'];
        $results ='';
        foreach ( $packages as $package){
            if($package['name']==$projectName){
                return $package['version'];
            }
        }
        return  $results;
    }

    /**
     * 获取composer.json的依赖包名称
     * @param $file
     * @param bool $env
     * @return array
     */
    public static function getRequire($file,$env=true){
        $requires = $names=[];
        if(file_exists($file)){
            $json = file_get_contents($file);
            $arr =json_decode($json,true);
            if($env){
                $requires = !empty($arr['require'])? $arr['require']:[];
            }else{
                $requires1 = !empty($arr['require'])? $arr['require']:[];
                $requires2 = !empty($arr['require-dev'])? $arr['require-dev']:[];
                $requires = array_merge($requires1,$requires2);
//                $requires = !empty($arr['require-dev'])? $arr['require-dev']:[];
//                logObject($requires2);
            }
            $names = array_keys($requires);
        }
        return $names;
    }

    /**
     * 递归获取所以第三方插件
     * @param array $data
     * @param $projectName
     */
    public  function getRely($projectName,&$data=[]){
        $tmp = self::getRequire($this->vendorDir.'/'.$projectName."/composer.json");
        if(!empty($tmp)) {
            foreach ($tmp as $value) {
                $data[$projectName][$value]=[] ;
                $tmp2 =self::getRequire($this->vendorDir.'/'.$value."/composer.json");
                if(!empty($tmp2)){
                    self::getRely($value,$data[$projectName][$value]);
                }

            }
        }
    }

    /**
     * 判断节点是否存在
     * @param $projectName
     * @return bool
     */
    public function isset_node($projectName){
        foreach ($this->data['nodes'] as $node){
            if($node['name'] == $projectName){
                return true;
            }
        }
        return  false;
    }

    /**
     * 获取节点id
     * @param $nodeName
     * @return mixed
     */
    public  function getNodeId($nodeName){
        foreach ($this->data['nodes'] as $node){
            if($node['name'] == $nodeName){
                return $node['id'];
            }
        }
    }

    /**
     * 递归创建Echarts数据结构
     * @param $fatherId
     * @param $categoryId
     * @param $nodeName
     * @param $nodes
     * @param $data
     */
    public  function  recursionNodes($fatherId,$categoryId,$nodeName,$nodes,&$data){
        if(!$this->isset_node($nodeName)){
            $nodeId =count($data['nodes']);
            if($nodeId ==0){
                $data['nodes'][]=[
                    "id" => $nodeId,
                    "name" => $nodeName,
                    "symbolSize" => 20,
                    "value" => $this->getVersion($nodeName),
                    "category" => $categoryId
                ];
            }else{
                $data['nodes'][]=[
                    "id" => $nodeId,
                    "name" => $nodeName,
                    "value" => $this->getVersion($nodeName),
                    "category" => $categoryId
                ];
            }

            if($nodeId !==$fatherId){
                $data['links'][]=[
                    "source" => $nodeId,
                    "target" => $fatherId
                ];
            }
        }else{
            $nodeId = $this->getNodeId($nodeName);
            // 要现实复杂依赖关系,请取消注释
//            if($nodeId !==$fatherId){
//                $data['links'][]=[
//                    "source" => $nodeId,
//                    "target" => $fatherId
//                ];
//            }
        }



        if (!empty($nodes)){
            $categoryId = count( $this->data["categories"]);
            $this->data["categories"][]=["name"=>$nodeName];
            foreach ($nodes as $name=>$v){
                $this->recursionNodes($nodeId,$categoryId,$name,$v,$data);
            }
        }

    }


    /**
     * 解析依赖,并创建eCharts数据结构
     * @return array
     */
    public function getRequireAll(){
        // 获取所有加载的拓展
        $base = self::getRequire($this->baseComposerJson,$this->env);
        $this->_require[$this->projectName]=[];
        foreach ($base as $value){
            $this->_require[$this->projectName][$value]=[];
            $this->getRely($value, $this->_require[$this->projectName][$value]);
        }
        $results = $this->_require;
        $nodeId = $categoriesId = 0;
        foreach ($results as $key =>$value){
            $this->recursionNodes($nodeId,$categoriesId,$key,$value,$this->data);
            $categoriesId++;
        }
       return  $this->data;
    }

    /**
     * 直接生成html文件
     * @return string
     */
    public function renderHtml(){
        $json_str = json_encode( $this->getRequireAll(),true);
        return <<<HTML
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
</head>
<body>
    <div id="container" style="width: 100%;height: 800px"></div>
</body>
<script type="text/javascript" src="https://fastly.jsdelivr.net/npm/jquery"></script>
<script type="text/javascript" src="https://fastly.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
<script>
    var dom = document.getElementById('container');
    var myChart = echarts.init(dom, null, {
        renderer: 'canvas',useDirtyRect: false
    });
    var graph = {$json_str}
    var option= {
      tooltip: {},
      legend: [
        {
          data: graph.categories.map(function (a) {
            return a.name;
          })
        }
      ],
      series: [
        {
          name: 'shiguangxiaotou/crud',
          type: 'graph',
          layout: 'force',
          data: graph.nodes,
          links: graph.links,
          categories: graph.categories,
          roam: true,
          label: {
            show: true,
            position: 'right',
            formatter: '{b}'
          },
          labelLayout: {
            hideOverlap: true
          },
          scaleLimit: {
            min: 2,
            max: 10
          },
          lineStyle: {
            color: 'source',
            curveness: 0.3
          }
        }
      ]
    };
    myChart.showLoading();
    myChart.hideLoading();
    myChart.setOption(option);
    if (option && typeof option === 'object') {
      myChart.setOption(option);
    }
    window.addEventListener('resize', myChart.resize);
</script>
</html>
HTML;
    }

}
This entry was posted in php and tagged . Bookmark the permalink.

发表回复