public function run()
 {
     // 前回のデータを取得
     $oldCards = $this->converter->convert($this->reader->read(storage_path() . $this->lastDataFile, '[]'));
     if (is_null($oldCards)) {
         return false;
     }
     // URL生成
     $url = 'https://trello.com/1/lists/' . env('TRELLO_LIST_ID') . '/cards' . '?key=' . env('TRELLO_KEY') . '&token=' . env('TRELLO_TOKEN');
     // Trelloよりカード情報取得
     if (false === ($json = $this->getter->get($url))) {
         return false;
     }
     // 取得したカード情報(JSON形式)を配列へ変換
     if (is_null($cards = $this->converter->convert($json))) {
         return false;
     }
     $created = new CardCreated();
     $updated = new CardUpdated();
     $currentCards = [];
     foreach ($cards as $card) {
         // 保存用データ作成
         $id = $card['id'];
         // 日本時間で保存したほうが分かりやすい
         $carbonTime = (new Carbon($card['dateLastActivity']))->timezone('Asia/Tokyo');
         $timeString = $carbonTime->toDateTimeString();
         $currentCards[$id] = $timeString;
         // 直前のデーターに存在していなければ新規カード
         if (!array_key_exists($id, $oldCards)) {
             $created->id = $id;
             $created->name = $card['name'];
             $created->time = $carbonTime;
             $this->dispatcher->fire($created);
             continue;
         }
         // IDが一致するのに最終更新時間が異なっていれば更新
         if ($timeString !== $oldCards[$id]) {
             $updated->id = $id;
             $updated->name = $card['name'];
             $updated->time = $carbonTime;
             $this->dispatcher->fire($updated);
         }
     }
     $deleted = new CardDeleted();
     // 削除されたカードを選択
     $deletedCards = array_diff_key($oldCards, $currentCards);
     foreach ($deletedCards as $deletedId => $time) {
         $deleted->id = $deletedId;
         $this->dispatcher->fire($deleted);
     }
     // 今回の取得データをファイルへ保存
     $this->file->put(storage_path() . $this->lastDataFile, json_encode($currentCards));
     return true;
 }
 public function run($url)
 {
     // 前回のデータを取得
     $lastFeedFilename = storage_path() . $this->convertUrlToFileName($url);
     $lastFeedTime = $this->reader->read($lastFeedFilename, '2000-01-01 00:00:00');
     // 保存していた最終アイテムの投稿時間を取得
     $lastTime = Carbon::createFromFormat('Y-m-d H:i:s', trim($lastFeedTime), 'Asia/Tokyo');
     // RSS取得
     try {
         $fastFeed = Factory::create();
         $fastFeed->addFeed('default', $url);
         $items = $fastFeed->fetch('default');
     } catch (Exception $e) {
         Log::error('RSS取得失敗。' . $e->getMessage());
         return false;
     }
     // 取得できなければ終了
     if (empty($items)) {
         return false;
     }
     $event = new FeedPosted();
     foreach ($items as $item) {
         // 以前の最新フィードより新しい物だけを処理
         $itemTime = Carbon::instance($item->getDate());
         if ($itemTime->gt($lastTime)) {
             // 取得情報をイベントへ!!
             $event->author = $item->getAuthor();
             $event->content = html_entity_decode($item->getContent());
             $event->date = Carbon::instance($item->getDate());
             $event->id = $item->getId();
             $event->image = $item->getImage();
             $event->intro = html_entity_decode($item->getIntro());
             $event->name = html_entity_decode($item->getName());
             $event->source = $item->getSource();
             $event->tags = $item->getTags();
             // イベント発行
             $this->dispatcher->fire($event);
         }
     }
     if (count($items) >= 1) {
         // 最新アイテムの投稿時間を
         // 目認しやすいように日本時間で保存する
         $latestTime = Carbon::instance(head($items)->getDate());
         $this->file->put($lastFeedFilename, $latestTime->timezone('Asia/Tokyo')->toDateTimeString());
     }
     return true;
 }
 public function run($url, $timeout)
 {
     $now = Carbon::now();
     // 前回のデータを取得
     // totalDownは今回使用しないが、統計情報が必要になったら使える
     // 日時取得のオーバーヘッドが大きいなら、初期時の処理をクロージャーにするなど
     // 工夫が必要かもしれない(現状文字列で渡しているため、毎回評価される)
     $lastData = $this->converter->convert($this->reader->read(storage_path() . $this->convertUrlToFileName($url), '{' . '"startedAt": "' . $now->toDateTimeString() . '",' . '"totalDown": "0",' . '"status": "down",' . '"lastChangedAt": "' . $now->toDateTimeString() . '"' . '}'));
     // curlで接続
     $curl = curl_init($url);
     // オプション指定、サイトに合わせて調節
     $options = [CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => $timeout];
     curl_setopt_array($curl, $options);
     // 呼び出し
     $result = curl_exec($curl);
     // 接続時間や転送時間などログしておくと統計情報に利用できる情報の配列
     // 今回はステータスコード以外未使用、未保存
     $info = curl_getinfo($curl);
     curl_close($curl);
     // 状態がダウンに変わった場合
     if ($lastData['status'] === 'up' && (!$result || $info['http_code'] !== 200)) {
         $lastData['status'] = 'down';
         $lastData['lastChangedAt'] = $now->toDateTimeString();
         $siteDown = new SiteDowned();
         $siteDown->url = $url;
         $siteDown->time = $now;
         $siteDown->code = $info['http_code'];
         $this->dispatcher->fire($siteDown);
     }
     // 状態がアップに変わった場合
     if ($lastData['status'] === 'down' && $result && $info['http_code'] === 200) {
         $lastData['status'] = 'up';
         $lastData['totalDown'] += Carbon::createFromFormat('Y-m-d H:i:s', $lastData['lastChangedAt'])->diffInMinutes($now);
         $lastData['lastChangedAt'] = $now->toDateTimeString();
         $siteUp = new SiteUpped();
         $siteUp->url = $url;
         $siteUp->time = $now;
         $this->dispatcher->fire($siteUp);
     }
     // データの保存
     $this->file->put(storage_path() . $this->convertUrlToFileName($url), json_encode($lastData));
 }