px-files/_sys/php/commands/publish.php
private function exec_publish( $px ){
		header('Content-type: text/plain;');
		$total_time = time();
		print $this->cli_header();

		$validate = $this->validate();
		if( !$validate['status'] ){
			print $validate['message']."\n";
			print $this->cli_footer();
			exit;
		}
		flush();
		if( !$this->lock() ){//ロック
			print '------'."\n";
			print 'publish is now locked.'."\n";
			print '  (lockfile updated: '.@date('Y-m-d H:i:s', filemtime($this->path_lockfile)).')'."\n";
			print 'Try again later...'."\n";
			print 'exit.'."\n";
			print $this->cli_footer();
			exit;
		}
		print "\n";
		print "\n";

		print '============'."\n";
		print '## Clearing caches'."\n";
		print "\n";
		$this->clearcache();
		print "\n";

		// make instance $site
		$this->px->set_site( new \picklesFramework2\site($this->px) );

		print '============'."\n";
		print '## Making list'."\n";
		print "\n";
		print '-- making list by Sitemap'."\n";
		$this->make_list_by_sitemap();
		print "\n";
		print '-- making list by Directory Scan'."\n";
		foreach( $this->get_region_root_path() as $path_region ){
			$this->make_list_by_dir_scan( $path_region );
		}
		print "\n";
		print '============'."\n";
		print '## Start publishing'."\n";
		print "\n";
		print $this->cli_report();
		print "\n";

		while(1){
			set_time_limit(5*60);
			flush();
			if( !count( $this->paths_queue ) ){
				break;
			}
			foreach( $this->paths_queue as $path=>$val ){break;}
			print '------------'."\n";
			print $path."\n";
			$path_type = $this->px->get_path_type( $path );
			if( $path_type != 'normal' && $path_type !== false ){
				// 物理ファイルではないものはスキップ
				print ' -> Non file URL.'."\n";

			}elseif( $this->px->fs()->is_dir(dirname($_SERVER['SCRIPT_FILENAME']).$path) ){
				// ディレクトリを処理
				$this->px->fs()->mkdir( $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path );
				print ' -> A directory.'."\n";

			}else{
				// ファイルを処理
				$ext = strtolower( pathinfo( $path , PATHINFO_EXTENSION ) );
				$proc_type = $this->px->get_path_proc_type( $path );
				$status_code = null;
				$status_message = null;
				$errors = array();
				$microtime = microtime(true);
				switch( $proc_type ){
					case 'pass':
						// pass
						print $ext.' -> '.$proc_type."\n";
						if( !$this->px->fs()->mkdir_r( dirname( $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path ) ) ){
							$status_code = 500;
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'FAILED to making parent directory.' ));
							break;
						}
						if( !$this->px->fs()->copy( dirname($_SERVER['SCRIPT_FILENAME']).$path , $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path ) ){
							$status_code = 500;
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'FAILED to copying file.' ));
							break;
						}
						$status_code = 200;
						break;

					case 'direct':
					default:
						// pickles execute
						print $ext.' -> '.$proc_type."\n";

						$bin = $this->px->internal_sub_request( $path, array('output'=>'json'), $return_var );
						if( !is_object($bin) ){
							$bin = new \stdClass;
							$bin->status = 500;
							$tmp_err_msg = 'Unknown server error';
							$tmp_err_msg .= "\n".'PHP returned status code "'.$return_var.'" on exit. There is a possibility of "Parse Error" or "Fatal Error" was occured.';
							$tmp_err_msg .= "\n".'Hint: Normally, "Pickles 2" content files are parsed as PHP scripts. If you are using "<'.'?", "<'.'?php", "<'.'%", or "<'.'?=" unintentionally in contents, might be the cause.';
							$bin->message = $tmp_err_msg;
							$bin->errors = array();
							// $bin->errors = array($tmp_err_msg);
							$bin->relatedlinks = array();
							$bin->body_base64 = base64_encode('');
							// $bin->body_base64 = base64_encode($tmp_err_msg);
							unset($tmp_err_msg);
						}
						$status_code = @$bin->status;
						$status_message = @$bin->message;
						$errors = @$bin->errors;
						if( $bin->status >= 500 ){
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'status: '.$bin->status.' '.$bin->message ));
						}elseif( $bin->status >= 400 ){
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'status: '.$bin->status.' '.$bin->message ));
						}elseif( $bin->status >= 300 ){
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'status: '.$bin->status.' '.$bin->message ));
						}elseif( $bin->status >= 200 ){
							// 200 番台は正常
						}elseif( $bin->status >= 100 ){
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'status: '.$bin->status.' '.$bin->message ));
						}else{
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'Unknown status code.' ));
						}

						// コンテンツの書き出し処理
						// エラーが含まれている場合でも、得られたコンテンツを出力する。
						$this->px->fs()->mkdir_r( dirname( $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path ) );
						$this->px->fs()->save_file( $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path, base64_decode( @$bin->body_base64 ) );
						foreach( $bin->relatedlinks as $link ){
							$link = $this->px->fs()->get_realpath( $link, dirname($this->path_docroot.$path).'/' );
							$link = $this->px->fs()->normalize_path( $link );
							$tmp_link = preg_replace( '/^'.preg_quote($this->px->get_path_controot(), '/').'/s', '/', $link );
							if( $this->px->fs()->is_dir( $this->px->get_realpath_docroot().'/'.$link ) ){
								$this->make_list_by_dir_scan( $tmp_link.'/' );
							}else{
								$this->add_queue( $tmp_link );
							}
						}

						// エラーメッセージを alert_log に追記
						if( is_array( $bin->errors ) && count( $bin->errors ) ){
							foreach( $bin->errors as $tmp_error_row ){
								$this->alert_log(array( @date('Y-m-d H:i:s'), $path, $tmp_error_row ));
							}
						}

						break;
				}

				$str_errors = '';
				if( is_array($errors) && count($errors) ){
					$str_errors .= count($errors).' errors: ';
					$str_errors .= implode(', ', $errors).';';
				}
				$this->log(array(
					@date('Y-m-d H:i:s') ,
					$path ,
					$proc_type ,
					$status_code ,
					$status_message ,
					$str_errors,
					@filesize($this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path),
					microtime(true)-$microtime
				));

			}

			if( !empty( $this->path_publish_dir ) ){
				// パブリッシュ先ディレクトリに都度コピー
				if( $this->px->fs()->is_file( $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path ) ){
					$this->px->fs()->mkdir_r( dirname( $this->path_publish_dir.$this->path_docroot.$path ) );
					$this->px->fs()->copy(
						$this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path ,
						$this->path_publish_dir.$this->path_docroot.$path
					);
					print ' -> copied to publish dir'."\n";
				}
			}

			unset($this->paths_queue[$path]);
			$this->paths_done[$path] = true;
			print $this->cli_report();

			$this->touch_lockfile();

			if( !count( $this->paths_queue ) ){
				break;
			}
		}

		print "\n";

		if( !empty( $this->path_publish_dir ) ){
			// パブリッシュ先ディレクトリを同期
			print '============'."\n";
			print '## Sync to publish directory.'."\n";
			print "\n";
			set_time_limit(30*60);
			foreach( $this->paths_region as $path_region ){
				$this->sync_dir(
					$this->path_tmp_publish.'/htdocs'.$this->path_docroot ,
					$this->path_publish_dir.$this->path_docroot ,
					$path_region
				);
			}
		}
		print "\n";
		print '============'."\n";
		print '## done.'."\n";
		print "\n";

		$path_logfile = $this->path_tmp_publish.'alert_log.csv';
		clearstatcache();
		if( @is_file( $path_logfile ) ){
			sleep(1);
			$alert_log = $this->px->fs()->read_csv( $path_logfile );
			array_shift( $alert_log );
			$alert_total_count = count($alert_log);
			$max_preview_count = 20;
			$alert_header = '************************* '.$alert_total_count.' ALERTS ******';
			print $alert_header."\n";
			print "\n";
			$counter = 0;
			foreach( $alert_log as $key=>$row ){
				$counter ++;
				// var_dump($row);
				$tmp_number = '  ['.($key+1).'] ';
				print $tmp_number;
				print preg_replace('/(\r\n|\r|\n)/s', '$1'.str_pad('', strlen($tmp_number), ' '), $row[2])."\n";
				print str_pad('', strlen($tmp_number), ' ').'  in '.$row[1]."\n";
				if( $counter >= $max_preview_count ){ break; }
			}
			if( $alert_total_count > $max_preview_count ){
				print '  [etc...]'."\n";
			}
			print "\n";
			print '    You got total '.$alert_total_count.' alerts.'."\n";
			print '    see more: '.realpath($path_logfile)."\n";
			print str_pad('', strlen($alert_header), '*')."\n";
			print "\n";
		}

		print 'Total Time: '.(time() - $total_time).' sec.'."\n";
		print "\n";

		$this->unlock();//ロック解除

		print $this->cli_footer();
		exit;
	}
private function exec_publish( $px ){
		header('Content-type: text/plain;');
		$total_time = time();
		print $this->cli_header();

		$validate = $this->validate();
		if( !$validate['status'] ){
			print $validate['message']."\n";
			print $this->cli_footer();
			exit;
		}
		flush();
		if( !$this->lock() ){//ロック
			print '------'."\n";
			print 'publish is now locked.'."\n";
			print '  (lockfile updated: '.@date('Y-m-d H:i:s', filemtime($this->path_lockfile)).')'."\n";
			print 'Try again later...'."\n";
			print 'exit.'."\n";
			print $this->cli_footer();
			exit;
		}
		print "\n";
		print "\n";

		print '============'."\n";
		print '## Clearing caches'."\n";
		print "\n";
		$this->clearcache();
		print "\n";

		// make instance $site
		$this->px->set_site( new \picklesFramework2\site($this->px) );

		print '============'."\n";
		print '## Making list'."\n";
		print "\n";
		print '-- making list by Sitemap'."\n";
		$this->make_list_by_sitemap();
		print "\n";
		print '-- making list by Directory Scan'."\n";
		foreach( $this->get_region_root_path() as $path_region ){
			$this->make_list_by_dir_scan( $path_region );
		}
		print "\n";
		print '============'."\n";
		print '## Start publishing'."\n";
		print "\n";
		print $this->cli_report();
		print "\n";

		while(1){
			set_time_limit(5*60);
			flush();
			if( !count( $this->paths_queue ) ){
				break;
			}
			foreach( $this->paths_queue as $path=>$val ){break;}
			print '------------'."\n";
			print $path."\n";
			$path_type = $this->px->get_path_type( $path );
			if( $path_type != 'normal' && $path_type !== false ){
				// 物理ファイルではないものはスキップ
				print ' -> Non file URL.'."\n";

			}elseif( $this->px->fs()->is_dir(dirname($_SERVER['SCRIPT_FILENAME']).$path) ){
				// ディレクトリを処理
				$this->px->fs()->mkdir( $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path );
				print ' -> A directory.'."\n";

			}else{
				// ファイルを処理
				$ext = strtolower( pathinfo( $path , PATHINFO_EXTENSION ) );
				$proc_type = $this->px->get_path_proc_type( $path );
				$status_code = null;
				$status_message = null;
				$errors = array();
				$microtime = microtime(true);
				switch( $proc_type ){
					case 'pass':
						// pass
						print $ext.' -> '.$proc_type."\n";
						if( !$this->px->fs()->mkdir_r( dirname( $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path ) ) ){
							$status_code = 500;
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'FAILED to making parent directory.' ));
							break;
						}
						if( !$this->px->fs()->copy( dirname($_SERVER['SCRIPT_FILENAME']).$path , $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path ) ){
							$status_code = 500;
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'FAILED to copying file.' ));
							break;
						}
						$status_code = 200;
						break;

					case 'direct':
					default:
						// pickles execute
						print $ext.' -> '.$proc_type."\n";

						$bin = $this->px->internal_sub_request( $path, array('output'=>'json'), $return_var );
						if( !is_object($bin) ){
							$bin = new \stdClass;
							$bin->status = 500;
							$tmp_err_msg = 'Unknown server error';
							$tmp_err_msg .= "\n".'PHP returned status code "'.$return_var.'" on exit. There is a possibility of "Parse Error" or "Fatal Error" was occured.';
							$tmp_err_msg .= "\n".'Hint: Normally, "Pickles 2" content files are parsed as PHP scripts. If you are using "<'.'?", "<'.'?php", "<'.'%", or "<'.'?=" unintentionally in contents, might be the cause.';
							$bin->message = $tmp_err_msg;
							$bin->errors = array();
							// $bin->errors = array($tmp_err_msg);
							$bin->relatedlinks = array();
							$bin->body_base64 = base64_encode('');
							// $bin->body_base64 = base64_encode($tmp_err_msg);
							unset($tmp_err_msg);
						}
						$status_code = @$bin->status;
						$status_message = @$bin->message;
						$errors = @$bin->errors;
						if( $bin->status >= 500 ){
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'status: '.$bin->status.' '.$bin->message ));
						}elseif( $bin->status >= 400 ){
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'status: '.$bin->status.' '.$bin->message ));
						}elseif( $bin->status >= 300 ){
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'status: '.$bin->status.' '.$bin->message ));
						}elseif( $bin->status >= 200 ){
							// 200 番台は正常
						}elseif( $bin->status >= 100 ){
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'status: '.$bin->status.' '.$bin->message ));
						}else{
							$this->alert_log(array( @date('Y-m-d H:i:s'), $path, 'Unknown status code.' ));
						}

						// コンテンツの書き出し処理
						// エラーが含まれている場合でも、得られたコンテンツを出力する。
						$this->px->fs()->mkdir_r( dirname( $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path ) );
						$this->px->fs()->save_file( $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path, base64_decode( @$bin->body_base64 ) );
						foreach( $bin->relatedlinks as $link ){
							$link = $this->px->fs()->get_realpath( $link, dirname($this->path_docroot.$path).'/' );
							$link = $this->px->fs()->normalize_path( $link );
							$tmp_link = preg_replace( '/^'.preg_quote($this->px->get_path_controot(), '/').'/s', '/', $link );
							if( $this->px->fs()->is_dir( $this->px->get_realpath_docroot().'/'.$link ) ){
								$this->make_list_by_dir_scan( $tmp_link.'/' );
							}else{
								$this->add_queue( $tmp_link );
							}
						}

						// エラーメッセージを alert_log に追記
						if( is_array( $bin->errors ) && count( $bin->errors ) ){
							foreach( $bin->errors as $tmp_error_row ){
								$this->alert_log(array( @date('Y-m-d H:i:s'), $path, $tmp_error_row ));
							}
						}

						break;
				}

				$str_errors = '';
				if( is_array($errors) && count($errors) ){
					$str_errors .= count($errors).' errors: ';
					$str_errors .= implode(', ', $errors).';';
				}
				$this->log(array(
					@date('Y-m-d H:i:s') ,
					$path ,
					$proc_type ,
					$status_code ,
					$status_message ,
					$str_errors,
					@filesize($this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path),
					microtime(true)-$microtime
				));

			}

			if( !empty( $this->path_publish_dir ) ){
				// パブリッシュ先ディレクトリに都度コピー
				if( $this->px->fs()->is_file( $this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path ) ){
					$this->px->fs()->mkdir_r( dirname( $this->path_publish_dir.$this->path_docroot.$path ) );
					$this->px->fs()->copy(
						$this->path_tmp_publish.'/htdocs'.$this->path_docroot.$path ,
						$this->path_publish_dir.$this->path_docroot.$path
					);
					print ' -> copied to publish dir'."\n";
				}
			}

			unset($this->paths_queue[$path]);
			$this->paths_done[$path] = true;
			print $this->cli_report();

			$this->touch_lockfile();

			if( !count( $this->paths_queue ) ){
				break;
			}
		}

		print "\n";

		if( !empty( $this->path_publish_dir ) ){
			// パブリッシュ先ディレクトリを同期
			print '============'."\n";
			print '## Sync to publish directory.'."\n";
			print "\n";
			set_time_limit(30*60);
			foreach( $this->paths_region as $path_region ){
				$this->sync_dir(
					$this->path_tmp_publish.'/htdocs'.$this->path_docroot ,
					$this->path_publish_dir.$this->path_docroot ,
					$path_region
				);
			}
		}
		print "\n";
		print '============'."\n";
		print '## done.'."\n";
		print "\n";

		$path_logfile = $this->path_tmp_publish.'alert_log.csv';
		clearstatcache();
		if( @is_file( $path_logfile ) ){
			sleep(1);
			$alert_log = $this->px->fs()->read_csv( $path_logfile );
			array_shift( $alert_log );
			$alert_total_count = count($alert_log);
			$max_preview_count = 20;
			$alert_header = '************************* '.$alert_total_count.' ALERTS ******';
			print $alert_header."\n";
			print "\n";
			$counter = 0;
			foreach( $alert_log as $key=>$row ){
				$counter ++;
				// var_dump($row);
				$tmp_number = '  ['.($key+1).'] ';
				print $tmp_number;
				print preg_replace('/(\r\n|\r|\n)/s', '$1'.str_pad('', strlen($tmp_number), ' '), $row[2])."\n";
				print str_pad('', strlen($tmp_number), ' ').'  in '.$row[1]."\n";
				if( $counter >= $max_preview_count ){ break; }
			}
			if( $alert_total_count > $max_preview_count ){
				print '  [etc...]'."\n";
			}
			print "\n";
			print '    You got total '.$alert_total_count.' alerts.'."\n";
			print '    see more: '.realpath($path_logfile)."\n";
			print str_pad('', strlen($alert_header), '*')."\n";
			print "\n";
		}

		print 'Total Time: '.(time() - $total_time).' sec.'."\n";
		print "\n";

		$this->unlock();//ロック解除

		print $this->cli_footer();
		exit;
	}
execute publish
@param object $px Picklesオブジェクト