2016-01-20 91 views
0

我想從我的PHP YII2框架中創建JIRA中的問題。 我想要做的是 - 每當我在我的系統中創建一個新版本時,我希望這個版本會自動創建一個問題JIRA。 我在CURL中找到了一些例子,但到目前爲止它不工作。 我甚至沒有收到任何錯誤消息。它在我的系統中創建了一個新版本,但在JIRA中沒有任何反應,看起來它甚至沒有嘗試連接到JIRA。使用REST API在JIRA中創建問題 - PHP YII2

這是我VersionController.php -

<?php 

namespace app\controllers; 

require_once("Curl.php"); 

use Yii; 
use app\models\Version; 
use app\models\VersionSearch; 
use app\models\Binfile; 
use app\models\VersionStatus; 
use yii\web\Controller; 
use yii\web\NotFoundHttpException; 
use yii\filters\VerbFilter; 
use yii\swiftmailer\Mailer; 
use yii\web\UnauthorizedHttpException; 
use linslin\yii2\curl; 
use understeam\yii2\httpclient; 
use understeam\yii2\jira; 

/** 
* VersionController implements the CRUD actions for Version model. 
*/ 



class VersionController extends Controller 
{ 
    public function behaviors() 
    { 
     return [ 
      'verbs' => [ 
       'class' => VerbFilter::className(), 
       'actions' => [ 
        'delete' => ['post'], 
       ], 
      ], 
      'access' => [ 
         'class' => \yii\filters\AccessControl::className(), 
         'only' => ['index','create','update','view'], 
         'rules' => [ 
          // allow authenticated users 
          [ 
           'allow' => true, 
           'roles' => ['@'], 
          ], 
          // everything else is denied 
         ], 
        ],    
     ]; 
    } 

    /** 
    * Lists all Version models. 
    * @return mixed 
    */ 



    public function actionIndex() 
    { 

     if (\Yii::$app->user->can('deleteVersion')) { 
      $template = '{view} {update} {delete} ';  
     } 
     else if((\Yii::$app->user->can('changeStatus')) || (\Yii::$app->user->can('uploadVersion'))){ 
      $template = '{view} {update}'; 
     } 
     else{$template = '{view}'; 
     } 


     $searchModel = new VersionSearch(); 
     $dataProvider = $searchModel->search(Yii::$app->request->queryParams); 

     return $this->render('index', [ 
      'searchModel' => $searchModel, 
      'dataProvider' => $dataProvider, 
      'template' => $template, 
     ]); 
    } 

    /** 
    * Displays a single Version model. 
    * @param integer $id 
    * @return mixed 
    */ 
    public function actionView($id) 
    { 
     return $this->render('view', [ 
      'model' => $this->findModel($id), 
     ]); 
    } 

    /** 
    * Creates a new Version model. 
    * If creation is successful, the browser will be redirected to the 'view' page. 
    * @return mixed 
    */ 
    public function actionCreate() 
    { 
     if(!\Yii::$app->user->can('createVersion')){ 
      throw new UnauthorizedHttpException("Access denied: You don't have permission to create a version"); 
     }else{ 
       $model = new Version(); 

       if ($model->load(Yii::$app->request->post()) && $model->save()) { 
        //$this->actionSend(); 
        $this->actionPostExample(); 
       // $this->actionGetExample(); 

        return $this->redirect(['view', 'id' => $model->id]); 

       } else { 
        return $this->render('create', [ 
         'model' => $model, 
        ]); 
       } 
     } 
    } 

    /** 
    * Updates an existing Version model. 
    * If update is successful, the browser will be redirected to the 'view' page. 
    * @param integer $id 
    * @return mixed 
    */ 
    public function actionUpdate($id) 
    { 
     $model = $this->findModel($id); 

     if ($model->load(Yii::$app->request->post()) && $model->save()) { 
      return $this->redirect(['view', 'id' => $model->id]); 
     } else { 
      return $this->render('update', [ 
       'model' => $model, 
      ]); 
     } 
    } 

    /** 
    * Deletes an existing Version model. 
    * If deletion is successful, the browser will be redirected to the 'index' page. 
    * @param integer $id 
    * @return mixed 
    */ 
    public function actionDelete($id) 
    { 
     if(!\Yii::$app->user->can('isAdmin')){ 
      throw new UnauthorizedHttpException("Access denied: Only Admin can perform this action!!!"); 
     }else{ 
       $this->findModel($id)->delete(); 

       return $this->redirect(['index']); 
     } 
    } 

    /** 
    * Finds the Version model based on its primary key value. 
    * If the model is not found, a 404 HTTP exception will be thrown. 
    * @param integer $id 
    * @return Version the loaded model 
    * @throws NotFoundHttpException if the model cannot be found 
    */ 
    protected function findModel($id) 
    { 
     if (($model = Version::findOne($id)) !== null) { 
      return $model; 
     } else { 
      throw new NotFoundHttpException('The requested page does not exist.'); 
     } 
    } 

    public function actionSend() 
    { 
     Yii::$app->mailer->compose() 
     ->setFrom('[email protected]') 
     ->setTo('[email protected]') 
     ->setSubject('Message test') 
     ->setTextBody('Plain text content') 
     ->setHtmlBody('<b>test</b>') 
     ->send(); 

    } 

    public function actionPostExample() 
    { 


      define('JIRA_URL', 'http://jiratest.../'); 
      define('USERNAME', 'jenya'); 
      define('PASSWORD', 'password'); 



      function post_to($resource, $data) 
      { 
       $jdata = json_encode($data); 
       $ch = curl_init(); 
       curl_setopt_array($ch, array(
       CURLOPT_POST => 1, 
       CURLOPT_URL => JIRA_URL . '/rest/api/latest/' . $resource, 
       CURLOPT_USERPWD => USERNAME . ':' . PASSWORD, 
       CURLOPT_POSTFIELDS => $jdata, 
       CURLOPT_HTTPHEADER => array('Content-type: application/json'), 
       CURLOPT_RETURNTRANSFER => true 
      )); 
      $result = curl_exec($ch); 
      curl_close($ch); 
      return json_decode($result); 
      } 


      $new_issue = array(
       'fields' => array(
       'project' => array('key' => 'key'), 
       'issuetype' => array('name' => 'Version Integration Task'), 
       'summary' => 'Test via REST', 
       'components' => 'General', 
       'customfield_10110' => 'name of value', 
       'fixVersions' => 'name of version', 
       'Description' => 'Description of issue goes here.', 

       //'labels' => array('a','b') 
       ) 
      ); 

     function create_issue($issue) 
     { 
      return post_to('issue', $issue); 
     } 

     $result = create_issue($new_issue); 

     if (property_exists($this, 'errors')) 
     { 
      echo "Error(s) creating issue:\n"; 
      var_dump($result); 
     } 
     else 
     { 
      echo "New issue created at " . JIRA_URL ."/browse/{$result}\n"; 
     } 

    } 

} 

Curl.php-

<?php 
/** 
* Yii2 cURL wrapper 
* With RESTful support. 
* 
* @category Web-yii2 
* @package yii2-curl 
* @author Nils Gajsek <[email protected]> 
* @copyright 2013-2015 Nils Gajsek<[email protected]> 
* @license http://opensource.org/licenses/MIT MIT Public 
* @version 1.0.7 
* @link  http://www.linslin.org 
* 
*/ 

namespace linslin\yii2\curl; 

use Yii; 
use yii\base\Exception; 
use yii\helpers\Json; 
use yii\web\HttpException; 

/** 
* cURL class 
*/ 
class Curl 
{ 

    // ################################################ class vars // ################################################ 


    /** 
    * @var string 
    * Holds response data right after sending a request. 
    */ 
    public $response = null; 

    /** 
    * @var integer HTTP-Status Code 
    * This value will hold HTTP-Status Code. False if request was not successful. 
    */ 
    public $responseCode = null; 

    /** 
    * @var array HTTP-Status Code 
    * Custom options holder 
    */ 
    private $_options = array(); 


    /** 
    * @var object 
    * Holds cURL-Handler 
    */ 
    private $_curl = null; 


    /** 
    * @var array default curl options 
    * Default curl options 
    */ 
    private $_defaultOptions = array(
     CURLOPT_USERAGENT  => 'Yii2-Curl-Agent', 
     CURLOPT_TIMEOUT  => 30, 
     CURLOPT_CONNECTTIMEOUT => 30, 
     CURLOPT_RETURNTRANSFER => true, 
     CURLOPT_HEADER   => false, 
    ); 



    // ############################################### class methods // ############################################## 

    /** 
    * Start performing GET-HTTP-Request 
    * 
    * @param string $url 
    * @param boolean $raw if response body contains JSON and should be decoded 
    * 
    * @return mixed response 
    */ 
    public function get($url, $raw = true) 
    { 
     return $this->_httpRequest('GET', $url, $raw); 
    } 


    /** 
    * Start performing HEAD-HTTP-Request 
    * 
    * @param string $url 
    * 
    * @return mixed response 
    */ 
    public function head($url) 
    { 
     return $this->_httpRequest('HEAD', $url); 
    } 


    /** 
    * Start performing POST-HTTP-Request 
    * 
    * @param string $url 
    * @param boolean $raw if response body contains JSON and should be decoded 
    * 
    * @return mixed response 
    */ 
    public function post($url, $raw = true) 
    { 
     return $this->_httpRequest('POST', $url, $raw); 
    } 


    /** 
    * Start performing PUT-HTTP-Request 
    * 
    * @param string $url 
    * @param boolean $raw if response body contains JSON and should be decoded 
    * 
    * @return mixed response 
    */ 
    public function put($url, $raw = true) 
    { 
     return $this->_httpRequest('PUT', $url, $raw); 
    } 


    /** 
    * Start performing DELETE-HTTP-Request 
    * 
    * @param string $url 
    * @param boolean $raw if response body contains JSON and should be decoded 
    * 
    * @return mixed response 
    */ 
    public function delete($url, $raw = true) 
    { 
     return $this->_httpRequest('DELETE', $url, $raw); 
    } 


    /** 
    * Set curl option 
    * 
    * @param string $key 
    * @param mixed $value 
    * 
    * @return $this 
    */ 
    public function setOption($key, $value) 
    { 
     //set value 
     if (in_array($key, $this->_defaultOptions) && $key !== CURLOPT_WRITEFUNCTION) { 
      $this->_defaultOptions[$key] = $value; 
     } else { 
      $this->_options[$key] = $value; 
     } 

     //return self 
     return $this; 
    } 


    /** 
    * Unset a single curl option 
    * 
    * @param string $key 
    * 
    * @return $this 
    */ 
    public function unsetOption($key) 
    { 
     //reset a single option if its set already 
     if (isset($this->_options[$key])) { 
      unset($this->_options[$key]); 
     } 

     return $this; 
    } 


    /** 
    * Unset all curl option, excluding default options. 
    * 
    * @return $this 
    */ 
    public function unsetOptions() 
    { 
     //reset all options 
     if (isset($this->_options)) { 
      $this->_options = array(); 
     } 

     return $this; 
    } 


    /** 
    * Total reset of options, responses, etc. 
    * 
    * @return $this 
    */ 
    public function reset() 
    { 
     if ($this->_curl !== null) { 
      curl_close($this->_curl); //stop curl 
     } 

     //reset all options 
     if (isset($this->_options)) { 
      $this->_options = array(); 
     } 

     //reset response & status code 
     $this->_curl = null; 
     $this->response = null; 
     $this->responseCode = null; 

     return $this; 
    } 


    /** 
    * Return a single option 
    * 
    * @param string|integer $key 
    * @return mixed|boolean 
    */ 
    public function getOption($key) 
    { 
     //get merged options depends on default and user options 
     $mergesOptions = $this->getOptions(); 

     //return value or false if key is not set. 
     return isset($mergesOptions[$key]) ? $mergesOptions[$key] : false; 
    } 


    /** 
    * Return merged curl options and keep keys! 
    * 
    * @return array 
    */ 
    public function getOptions() 
    { 
     return $this->_options + $this->_defaultOptions; 
    } 


    /** 
    * Get curl info according to http://php.net/manual/de/function.curl-getinfo.php 
    * 
    * @return mixed 
    */ 
    public function getInfo($opt = null) 
    { 
     if ($this->_curl !== null && $opt === null) { 
      return curl_getinfo($this->_curl); 
     } elseif ($this->_curl !== null && $opt !== null) { 
      return curl_getinfo($this->_curl, $opt); 
     } else { 
      return []; 
     } 
    } 


    /** 
    * Performs HTTP request 
    * 
    * @param string $method 
    * @param string $url 
    * @param boolean $raw if response body contains JSON and should be decoded -> helper. 
    * 
    * @throws Exception if request failed 
    * 
    * @return mixed 
    */ 
    private function _httpRequest($method, $url, $raw = false) 
    { 
     //set request type and writer function 
     $this->setOption(CURLOPT_CUSTOMREQUEST, strtoupper($method)); 

     //check if method is head and set no body 
     if ($method === 'HEAD') { 
      $this->setOption(CURLOPT_NOBODY, true); 
      $this->unsetOption(CURLOPT_WRITEFUNCTION); 
     } 

     //setup error reporting and profiling 
     Yii::trace('Start sending cURL-Request: '.$url.'\n', __METHOD__); 
     Yii::beginProfile($method.' '.$url.'#'.md5(serialize($this->getOption(CURLOPT_POSTFIELDS))), __METHOD__); 

     /** 
     * proceed curl 
     */ 
     $this->_curl = curl_init($url); 
     curl_setopt_array($this->_curl, $this->getOptions()); 
     $body = curl_exec($this->_curl); 

     //check if curl was successful 
     if ($body === false) { 
      switch (curl_errno($this->_curl)) { 

       case 7: 
        $this->responseCode = 'timeout'; 
        return false; 
        break; 

       default: 
        throw new Exception('curl request failed: ' . curl_error($this->_curl) , curl_errno($this->_curl)); 
        break; 
      } 
     } 

     //retrieve response code 
     $this->responseCode = curl_getinfo($this->_curl, CURLINFO_HTTP_CODE); 
     $this->response = $body; 

     //end yii debug profile 
     Yii::endProfile($method.' '.$url .'#'.md5(serialize($this->getOption(CURLOPT_POSTFIELDS))), __METHOD__); 

     //check responseCode and return data/status 
     if ($this->getOption(CURLOPT_CUSTOMREQUEST) === 'HEAD') { 
      return true; 
     } else { 
      $this->response = $raw ? $this->response : Json::decode($this->response); 
      return $this->response; 
     } 
    } 
} 

我會很感激你的幫助,我不知道還有什麼嘗試。 在此先感謝。

+0

從JIRA(HTTP響應代碼和響應主體?)得到的錯誤是什麼?如果診斷響應沒有幫助,爲了進一步調試,我建議採用這種方法:捕獲用於創建問題的HTTP POST主體,刪除所有非必要的細節並通過捲曲手動提交,然後添加原始部分身體,直到東西破裂。如果最小問題JSON正文發佈在這裏,我會看看。 – antonycc

+0

問題是,我忘了在我原來的帖子中提到它 - 我沒有得到任何錯誤。沒有。就我而言,它在我的系統中創建了一個新版本,但在JIRA中沒有任何反應,在那裏沒有新的問題。 – Jenny

回答

0

VersionController.php/actionPostExample()/ post_to中存在一個錯誤。正如我寫的,我期望HTTP post到JIRA導致HTTP 404響應。

這條線:

CURLOPT_URL => JIRA_URL . '/rest/api/latest/' . $resource, 

應該是:

CURLOPT_URL => JIRA_URL . '/rest/api/2/' . $resource, 

../最新/ ......在JIRA API文檔頁面中使用,但它不是休息API的一部分。 .../rest/api/2/...與JIRA 6和7兼容。

+0

我修正了它,但沒有改變,正如我在上面的另一個評論中所說的 - 我沒有得到任何錯誤,如果它甚至不想與JIRA溝通。 – Jenny

+0

本節有點困惑: – antonycc

+0

'$ result = curl_exec($ ch);'看起來你可以通過調用'public function post($ url,$ raw = true)'來避免一些複雜性Curl.php。無論哪種情況,如果您在發出請求之前記錄消息,然後記錄結果,您可能會更好地瞭解它在做什麼。你應該總是得到某種HTTP結果好壞或超時。在刪除密碼時也很好(我不想在它仍然存在的時候引起注意) – antonycc

0

我做到了。 這是對我的作品的功能:

function post_to($resource, $data) 
     { 
      $jdata = json_encode($data); 
      $ch = curl_init(); 
      curl_setopt_array($ch, array(
      CURLOPT_POST => true, 
      CURLOPT_URL => JIRA_URL . '/rest/api/latest/' . $resource, 
      CURLOPT_USERPWD => USERNAME . ':' . PASSWORD, 
      CURLOPT_POSTFIELDS => $jdata, 
      CURLOPT_HTTPHEADER => array('Content-type: application/json'), 
      CURLOPT_SSL_VERIFYPEER => false, 
      CURLOPT_SSL_VERIFYHOST => false, 
      //CURLOPT_RETURNTRANSFER => true 
     )); 

之後,我不得不修復JSON幾件事情是特定爲我的項目。

爲了便於調試,你可以補充一點:

error_reporting(E_ALL); 
     ini_set('display_errors', 1); 

得到清晰的錯誤。

+0

我們希望在我們的開發機器上設置E_ALL,然後在測試/ QA框中設置E_ALL〜E_NOTICE〜E_DEPRICATED。一旦開始生產,只有關鍵和例外設置。強迫開發人員編寫更好的代碼,但也可防止生產中無用的錯誤溢出。 –