当前位置: 首页>>代码示例>>PHP>>正文


PHP Tools::atk_in_array方法代码示例

本文整理汇总了PHP中Sintattica\Atk\Core\Tools::atk_in_array方法的典型用法代码示例。如果您正苦于以下问题:PHP Tools::atk_in_array方法的具体用法?PHP Tools::atk_in_array怎么用?PHP Tools::atk_in_array使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在Sintattica\Atk\Core\Tools的用法示例。


在下文中一共展示了Tools::atk_in_array方法的9个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的PHP代码示例。

示例1: search

 /**
  * Returns a piece of html code that can be used in a form to search.
  *
  * @param array $record Array with values
  * @param bool $extended if set to false, a simple search input is
  *                            returned for use in the searchbar of the
  *                            recordlist. If set to true, a more extended
  *                            search may be returned for the 'extended'
  *                            search page. The Attribute does not
  *                            make a difference for $extended is true, but
  *                            derived attributes may reimplement this.
  * @param string $fieldprefix The fieldprefix of this attribute's HTML element.
  * @param DataGrid $grid
  *
  * @return string Piece of html code
  */
 public function search($record, $extended = false, $fieldprefix = '', DataGrid $grid = null)
 {
     $this->createDestination();
     $id = $this->getHtmlId($fieldprefix);
     $name = $this->getSearchFieldName($fieldprefix);
     $selectOptions = [];
     $selectOptions['enable-select2'] = true;
     $selectOptions['dropdown-auto-width'] = true;
     $selectOptions['minimum-results-for-search'] = 10;
     if ($extended) {
         $selectOptions['placeholder'] = Tools::atktext('search_all');
     }
     //width always auto
     $selectOptions['width'] = 'auto';
     $selectOptions = array_merge($selectOptions, $this->m_select2Options['search']);
     $data = '';
     foreach ($selectOptions as $k => $v) {
         $data .= ' data-' . $k . '="' . htmlspecialchars($v) . '"';
     }
     // now select all records
     $recordset = $this->m_destInstance->select()->includes(Tools::atk_array_merge($this->m_destInstance->descriptorFields(), $this->m_destInstance->m_primaryKey))->getAllRows();
     $result = '<select class="form-control"' . $data;
     if ($extended) {
         $result .= 'multiple="multiple" size="' . min(5, count($recordset) + 1) . '"';
     }
     $result .= 'id="' . $id . '" name="' . $name . '[]">';
     $pkfield = $this->m_destInstance->primaryKeyField();
     if (!$extended) {
         $result .= '<option value="">' . Tools::atktext('search_all', 'atk') . '</option>';
     }
     for ($i = 0; $i < count($recordset); ++$i) {
         $pk = $recordset[$i][$pkfield];
         if (!empty($record[$this->fieldName()]) && Tools::atk_in_array($pk, $record[$this->fieldName()])) {
             $sel = ' selected="selected"';
         } else {
             $sel = '';
         }
         $result .= '<option value="' . $pk . '"' . $sel . '>' . $this->m_destInstance->descriptor($recordset[$i]) . '</option>';
     }
     $result .= '</select>';
     $result .= "<script>ATK.enableSelect2ForSelect('#{$id}');</script>";
     return $result;
 }
开发者ID:sintattica,项目名称:atk,代码行数:59,代码来源:ManyToManyRelation.php

示例2: validate

 /**
  * Validate a record.
  *
  * @param string $mode Override the mode
  * @param array $ignoreList Override the ignoreList
  */
 public function validate($mode = '', $ignoreList = array())
 {
     // check overrides
     if (count($ignoreList)) {
         $this->setIgnoreList($ignoreList);
     }
     if ($mode != '') {
         $this->setMode($mode);
     }
     Tools::atkdebug('validate() with mode ' . $this->m_mode . ' for node ' . $this->m_nodeObj->atkNodeUri());
     // set the record
     $record =& $this->m_record;
     // Check flags and values
     $db = $this->m_nodeObj->getDb();
     foreach ($this->m_nodeObj->m_attribIndexList as $attribdata) {
         $attribname = $attribdata['name'];
         if (!Tools::atk_in_array($attribname, $this->m_ignoreList)) {
             $p_attrib = $this->m_nodeObj->m_attribList[$attribname];
             $this->validateAttributeValue($p_attrib, $record);
             if ($p_attrib->hasFlag(Attribute::AF_PRIMARY) && !$p_attrib->hasFlag(Attribute::AF_AUTO_INCREMENT)) {
                 $atkorgkey = $record['atkprimkey'];
                 if ($atkorgkey == '' || $atkorgkey != $this->m_nodeObj->primaryKey($record)) {
                     $cnt = $this->m_nodeObj->select($this->m_nodeObj->primaryKey($record))->ignoreDefaultFilters(true)->ignorePostvars(true)->getRowCount();
                     if ($cnt > 0) {
                         Tools::triggerError($record, $p_attrib, 'error_primarykey_exists');
                     }
                 }
             }
             // if no root elements may be added to the tree, then every record needs to have a parent!
             if ($p_attrib->hasFlag(Attribute::AF_PARENT) && $this->m_nodeObj->hasFlag(TreeNode::NF_TREE_NO_ROOT_ADD) && $this->m_nodeObj->m_action == 'save') {
                 $p_attrib->m_flags |= Attribute::AF_OBLIGATORY;
             }
             // validate obligatory fields (but not the auto_increment ones, because they don't have a value yet)
             if ($p_attrib->hasFlag(Attribute::AF_OBLIGATORY) && !$p_attrib->hasFlag(Attribute::AF_AUTO_INCREMENT) && $p_attrib->isEmpty($record)) {
                 Tools::atkTriggerError($record, $p_attrib, 'error_obligatoryfield');
             } else {
                 if ($p_attrib->hasFlag(Attribute::AF_UNIQUE) && !$p_attrib->hasFlag(Attribute::AF_PRIMARY) && !$p_attrib->isEmpty($record)) {
                     $condition = $this->m_nodeObj->getTable() . ".{$attribname}='" . $db->escapeSQL($p_attrib->value2db($record)) . "'";
                     if ($this->m_mode != 'add') {
                         $condition .= ' AND NOT (' . $this->m_nodeObj->primaryKey($record) . ')';
                     }
                     $cnt = $this->m_nodeObj->select($condition)->ignoreDefaultFilters(true)->ignorePostvars(true)->getRowCount();
                     if ($cnt > 0) {
                         Tools::atkTriggerError($record, $p_attrib, 'error_uniquefield');
                     }
                 }
             }
         }
     }
     if (isset($record['atkerror']) && count($record['atkerror']) > 0) {
         for ($i = 0, $_i = count($record['atkerror']); $i < $_i; ++$i) {
             $record['atkerror'][$i]['node'] = $this->m_nodeObj->m_type;
         }
     }
     $this->validateUniqueFieldSets($record);
     if (isset($record['atkerror'])) {
         for ($i = 0, $_i = count($record['atkerror']); $i < $_i; ++$i) {
             $record['atkerror'][$i]['node'] = $this->m_nodeObj->m_type;
         }
         return false;
     }
     return true;
 }
开发者ID:sintattica,项目名称:atk,代码行数:69,代码来源:NodeValidator.php

示例3: edit

 /**
  * Returns a piece of html code that can be used in a form to edit this
  * attribute's value.
  *
  * @param array $record Array with fields
  * @param string $fieldprefix The fieldprefix to put in front of the name
  *                            of any html form element for this attribute.
  * @param string $mode The mode we're in ('add' or 'edit')
  *
  * @return string piece of html code with radioboxes
  */
 public function edit($record, $fieldprefix, $mode)
 {
     $id = $this->getHtmlId($fieldprefix);
     $name = $this->getHtmlName($fieldprefix);
     $page = Page::getInstance();
     $page->register_script(Config::getGlobal('assets_url') . 'javascript/class.atkprofileattribute.js');
     $result = '';
     if (!$this->hasFlag(self::AF_LINKS_BOTTOM)) {
         $result .= $this->_addLinks($fieldprefix);
     }
     $css = $this->getCSSClassAttribute('');
     $result .= '<div ' . $css . '>';
     $values = $this->getValues();
     if (!is_array($record[$this->fieldName()])) {
         $recordvalue = $this->db2value($record);
     } else {
         $recordvalue = $record[$this->fieldName()];
     }
     for ($i = 0; $i < count($values); ++$i) {
         $checkId = $id . '_' . $i;
         $checkName = $name . '[]';
         if (!$this->hasFlag(self::AF_CHECK_ALL)) {
             $sel = Tools::atk_in_array($values[$i], $recordvalue) ? 'checked' : '';
         } else {
             $sel = 'checked';
         }
         $result .= '<div>';
         $result .= '<input type="checkbox" id="' . $checkId . '" name="' . $checkName . '" value="' . $values[$i] . '" ' . $sel . '> ';
         $result .= $this->_translateValue($values[$i], $record);
         $result .= '</div>';
     }
     $result .= '</div>';
     if ($this->hasFlag(self::AF_LINKS_BOTTOM)) {
         $result .= $this->_addLinks($fieldprefix);
     }
     return $result;
 }
开发者ID:sintattica,项目名称:atk,代码行数:48,代码来源:MultiSelectAttribute.php

示例4: search

 /**
  * Returns a piece of html code that can be used to get search terms input
  * from the user.
  *
  * The framework calls this method to display the searchbox
  * in the search bar of the recordlist, and to display a more extensive
  * search in the 'extended' search screen.
  *
  * @todo Configurable rows
  *
  * @param array $record Array with values
  * @param bool $extended if set to false, a simple search input is
  *                            returned for use in the searchbar of the
  *                            recordlist. If set to true, a more extended
  *                            search may be returned for the 'extended'
  *                            search page. The Attribute does not
  *                            make a difference for $extended is true, but
  *                            derived attributes may reimplement this.
  * @param string $fieldprefix The fieldprefix of this attribute's HTML element.
  * @param DataGrid $grid
  *
  * @return string A piece of html-code with a checkbox
  */
 public function search($record, $extended = false, $fieldprefix = '', DataGrid $grid = null)
 {
     $values = $this->getValues();
     $id = $this->getHtmlId($fieldprefix);
     $name = $this->getSearchFieldName($fieldprefix);
     $isMultiple = $this->isMultipleSearch($extended);
     $class = $this->getCSSClassAttribute(['form-control']);
     $selectOptions = [];
     $selectOptions['enable-select2'] = true;
     $selectOptions['dropdown-auto-width'] = true;
     $selectOptions['minimum-results-for-search'] = 10;
     if ($isMultiple) {
         $selectOptions['placeholder'] = Tools::atktext('search_all');
     }
     //width always auto
     $selectOptions['width'] = 'auto';
     $selectOptions = array_merge($selectOptions, $this->m_select2Options['search']);
     $data = '';
     foreach ($selectOptions as $k => $v) {
         $data .= ' data-' . $k . '="' . htmlspecialchars($v) . '"';
     }
     $result = '<select ' . ($isMultiple ? 'multiple' : '') . ' ' . $class . ' id="' . $id . '" name="' . $name . '[]"' . $data . '>';
     $selValues = isset($record[$this->fieldName()]) ? $record[$this->fieldName()] : null;
     if (!is_array($selValues)) {
         $selValues = [$selValues];
     }
     if (in_array('', $selValues)) {
         $selValues = [''];
     }
     $selected = !$isMultiple && $selValues[0] == '' ? ' selected' : '';
     $option = Tools::atktext('search_all');
     $result .= sprintf('<option value=""%s>%s</option>', $selected, $option);
     // "none" option
     if (!$this->hasFlag(self::AF_OBLIGATORY) && !$this->hasFlag(self::AF_LIST_NO_NULL_ITEM)) {
         $selected = Tools::atk_in_array('__NONE__', $selValues) ? ' selected' : '';
         $option = Tools::atktext('search_none');
         $result .= sprintf('<option value="__NONE__"%s>%s</option>', $selected, $option);
     }
     // normal options
     foreach ($values as $value) {
         $selected = Tools::atk_in_array((string) $value, $selValues, true) ? ' selected' : '';
         $option = $this->_translateValue($value, $record);
         $result .= sprintf('<option value="%s"%s>%s</option>', $value, $selected, $option);
     }
     $result .= '</select>';
     $result .= "<script>ATK.enableSelect2ForSelect('#{$id}');</script>";
     // if we use autosearch, register an onchange event that submits the grid
     if (!is_null($grid) && !$extended && $this->m_autoSearch) {
         $onchange = $grid->getUpdateCall(array('atkstartat' => 0), [], 'ATK.DataGrid.extractSearchOverrides');
         $this->getOwnerInstance()->getPage()->register_loadscript('jQuery("#' . $id . '").on("change", function(){' . $onchange . '})');
     }
     return $result;
 }
开发者ID:sintattica,项目名称:atk,代码行数:76,代码来源:ListAttribute.php

示例5: addDb

 /**
  * Save a new record to the database.
  *
  * The record is passed by reference, because any autoincrement field gets
  * its value when stored to the database. The record is updated, so after
  * the call to addDb you can use access the primary key fields.
  *
  * NOTE: Does not commit your transaction! If you are using a database that uses
  * transactions you will need to call 'Db::getInstance()>commit()' manually.
  *
  * @param array $record The record to save.
  * @param bool $exectrigger Indicates whether the postAdd trigger
  *                            should be fired.
  * @param string $mode The mode we're in
  * @param array $excludelist List of attributenames that should be ignored
  *                            and not stored in the database.
  *
  * @return bool True if succesful, false if not.
  */
 public function addDb(&$record, $exectrigger = true, $mode = 'add', $excludelist = array())
 {
     if ($exectrigger) {
         if (!$this->executeTrigger('preAdd', $record, $mode)) {
             return Tools::atkerror('preAdd() failed!');
         }
     }
     $db = $this->getDb();
     $query = $db->createQuery();
     $storelist = array('pre' => [], 'post' => [], 'query' => array());
     $query->addTable($this->m_table);
     foreach (array_keys($this->m_attribList) as $attribname) {
         $p_attrib = $this->m_attribList[$attribname];
         if (!Tools::atk_in_array($attribname, $excludelist) && ($mode != 'add' || $p_attrib->needsInsert($record))) {
             $storemode = $p_attrib->storageType($mode);
             if (Tools::hasFlag($storemode, Attribute::PRESTORE)) {
                 $storelist['pre'][] = $attribname;
             }
             if (Tools::hasFlag($storemode, Attribute::POSTSTORE)) {
                 $storelist['post'][] = $attribname;
             }
             if (Tools::hasFlag($storemode, Attribute::ADDTOQUERY)) {
                 $storelist['query'][] = $attribname;
             }
         }
     }
     if (!$this->_storeAttributes($storelist['pre'], $record, $mode)) {
         return false;
     }
     for ($i = 0, $_i = count($storelist['query']); $i < $_i; ++$i) {
         $p_attrib = $this->m_attribList[$storelist['query'][$i]];
         $p_attrib->addToQuery($query, $this->m_table, '', $record, 1, 'add');
         // start at level 1
     }
     if (!$query->executeInsert()) {
         Tools::atkdebug('executeInsert failed..');
         return false;
     }
     // new primary key
     $record['atkprimkey'] = $this->primaryKey($record);
     if (!$this->_storeAttributes($storelist['post'], $record, $mode)) {
         Tools::atkdebug('_storeAttributes failed..');
         return false;
     }
     // Now we call a postAdd function, that can be used to do some processing after the record
     // has been saved.
     if ($exectrigger && !$this->executeTrigger('postAdd', $record, $mode)) {
         return false;
     }
     return true;
 }
开发者ID:sintattica,项目名称:atk,代码行数:70,代码来源:Node.php

示例6: preNotify

 /**
  * Notify the listener of any action about to be performed on a record.
  *
  * This method is called by the framework for each action called on a
  * node. Depending on the actionfilter passed in the constructor, the
  * call is forwarded to the preActionPerformed($action, $record) method.
  *
  * @param string $action The action about to be performed
  * @param array $record The record on which the action is about to be performed
  */
 public function preNotify($action, &$record)
 {
     if (count($this->m_actionfilter) == 0 || Tools::atk_in_array($action, $this->m_actionfilter)) {
         Tools::atkdebug("Action {$action} to be performed on " . $this->m_node->atkNodeUri() . ' (' . $this->m_node->primaryKey($record) . ')');
         $this->preActionPerformed($action, $record);
     }
 }
开发者ID:sintattica,项目名称:atk,代码行数:17,代码来源:ActionListener.php

示例7: edit

 /**
  * Returns a piece of html code that can be used in a form to edit this
  * attribute's value.
  *
  * @param array $record The record that holds the value for this attribute.
  * @param string $fieldprefix The fieldprefix to put in front of the name
  *                            of any html form element for this attribute.
  * @param string $mode The mode we're in ('add' or 'edit')
  *
  * @return string A piece of htmlcode for editing this attribute
  */
 public function edit($record, $fieldprefix, $mode)
 {
     $user = SecurityManager::atkGetUser();
     $page = Page::getInstance();
     $icons = "var ATK_PROFILE_ICON_OPEN = '" . Config::getGlobal('icon_plussquare') . "';";
     $icons .= "var ATK_PROFILE_ICON_CLOSE = '" . Config::getGlobal('icon_minussquare') . "';";
     $page->register_scriptcode($icons);
     $page->register_script(Config::getGlobal('assets_url') . 'javascript/class.atkprofileattribute.js');
     $this->_restoreDivStates($page);
     $result = '<div align="right">
               [<a href="javascript:void(0)" onclick="profile_checkAll(\'' . $this->fieldName() . '\'); return false;">' . Tools::atktext('check_all') . '</a> | <a href="javascript:void(0)" onclick="profile_checkNone(\'' . $this->fieldName() . '\'); return false;">' . Tools::atktext('check_none') . '</a> | <a href="javascript:void(0)" onclick="profile_checkInvert(\'' . $this->fieldName() . '\'); return false;">' . Tools::atktext('invert_selection') . '</a>]</div>';
     $isAdmin = $user['name'] == 'administrator' || $this->canGrantAll();
     $allActions = $this->getAllActions($record, true);
     $editableActions = $this->getEditableActions($record);
     $selectedActions = $this->getSelectedActions($record);
     foreach ($allActions as $section => $modules) {
         $result .= '<div class="profileSection">';
         $result .= "<span onclick=\"profile_swapProfileDiv('div_{$section}');\" style=\"cursor: pointer; font-size: 110%; font-weight: bold\">";
         $result .= '  <i class="' . Config::getGlobal('icon_plussquare') . "\" id=\"img_div_{$section}\"></i> " . Tools::atktext(array("title_{$section}", $section), $section);
         $result .= '</span><br/>';
         $result .= "<div id='div_{$section}' name='div_{$section}' style='display: none; padding-left: 15px' class='checkbox'>";
         $result .= "  <input type='hidden' name=\"divstate['div_{$section}']\" id=\"divstate['div_{$section}']\" value='closed' />";
         $result .= '  <div style="font-size: 80%; margin-top: 4px; margin-bottom: 4px" >
               [<a  style="font-size: 100%" href="javascript:void(0)" onclick="profile_checkAllByValue(\'' . $this->fieldName() . '\',\'' . $section . '.\'); return false;">' . Tools::atktext('check_all', 'atk') . '</a> | <a  style="font-size: 100%" href="javascript:void(0)" onclick="profile_checkNoneByValue(\'' . $this->fieldName() . '\',\'' . $section . '.\'); return false;">' . Tools::atktext('check_none', 'atk') . '</a> | <a  style="font-size: 100%" href="javascript:void(0)" onclick="profile_checkInvertByValue(\'' . $this->fieldName() . '\',\'' . $section . '.\'); return false;">' . Tools::atktext('invert_selection', 'atk') . '</a>]';
         $result .= '  </div>';
         $result .= '  <br>';
         foreach ($modules as $module => $nodes) {
             foreach ($nodes as $node => $actions) {
                 $showBox = $isAdmin || count(array_intersect($actions, is_array($editableActions[$module][$node]) ? $editableActions[$module][$node] : array())) > 0;
                 if ($showBox) {
                     $result .= '<b>' . Tools::atktext($node, $module) . '</b><br>';
                 }
                 $tabs_str = '';
                 $display_tabs_str = false;
                 // Draw action checkboxes
                 foreach ($actions as $action) {
                     $temp_str = '';
                     $isEditable = $isAdmin || Tools::atk_in_array($action, $editableActions[$module][$node]);
                     $isSelected = isset($selectedActions[$module][$node]) && in_array($action, $selectedActions[$module][$node]);
                     if ($isEditable) {
                         if (substr($action, 0, 4) == 'tab_') {
                             $display_tabs_str = true;
                         }
                         $temp_str .= '<label>';
                         $temp_str .= '<input type="checkbox" name="' . $this->fieldName() . '[]" ' . $this->getCSSClassAttribute('atkcheckbox') . ' value="' . $section . '.' . $module . '.' . $node . '.' . $action . '" ';
                         $temp_str .= ($isSelected ? ' checked="checked"' : '') . '>';
                         $temp_str .= ' ' . $this->permissionName($action, $node, $module);
                         $temp_str .= '</label>';
                     }
                     if (substr($action, 0, 4) == 'tab_') {
                         $tabs_str .= $temp_str;
                     } else {
                         $result .= $temp_str;
                     }
                 }
                 if ($display_tabs_str) {
                     $result .= '<br>Tabs:&nbsp;';
                 }
                 $result .= $tabs_str;
                 if ($showBox) {
                     $result .= "<br /><br />\n";
                 }
             }
         }
         $result .= '  </div>';
         // end div_$section
         $result .= '</div>';
         // end profileSection
     }
     return $result;
 }
开发者ID:sintattica,项目名称:atk,代码行数:82,代码来源:ProfileAttribute.php

示例8: showOnTab

 /**
  * Check if the attribute wants to be shown on a certain tab.
  *
  * @param string $tab The name of the tab to check.
  *
  * @return bool
  */
 public function showOnTab($tab)
 {
     return $this->getTabs() == '*' || Tools::atk_in_array($tab, $this->getTabs());
 }
开发者ID:sintattica,项目名称:atk,代码行数:11,代码来源:Attribute.php

示例9: edit

 /**
  * Returns a piece of html code that can be used in a form to edit this
  * attribute's value.
  *
  * @param array $record Array with fields
  * @param string $fieldprefix The fieldprefix to put in front of the name
  *                            of any html form element for this attribute.
  * @param string $mode The mode we're in ('add' or 'edit')
  *
  * @return string piece of html code with radioboxes
  */
 public function edit($record, $fieldprefix, $mode)
 {
     $id = $this->getHtmlId($fieldprefix);
     $name = $this->getHtmlName($fieldprefix);
     $selectOptions = [];
     $selectOptions['enable-select2'] = true;
     $selectOptions['dropdown-auto-width'] = true;
     $selectOptions['minimum-results-for-search'] = 10;
     $selectOptions['tags'] = true;
     if (!empty($this->getWidth())) {
         $selectOptions['width'] = $this->getWidth();
     } else {
         $selectOptions['width'] = 'auto';
     }
     $selectOptions['placeholder'] = $this->getNullLabel();
     $selectOptions = array_merge($selectOptions, $this->m_select2Options['edit']);
     $data = '';
     foreach ($selectOptions as $k => $v) {
         $data .= ' data-' . $k . '="' . htmlspecialchars($v) . '"';
     }
     $onchange = '';
     if (count($this->m_onchangecode)) {
         $onchange = ' onChange="' . $this->getHtmlId($fieldprefix) . '_onChange(this)"';
         $this->_renderChangeHandler($fieldprefix);
     }
     $result = '<select multiple id="' . $id . '" name="' . $name . '[]" ' . $this->getCSSClassAttribute('form-control') . '" ' . $onchange . $data . '>';
     $values = $this->getValues();
     if (!is_array($record[$this->fieldName()])) {
         $recordvalue = $this->db2value($record);
     } else {
         $recordvalue = $record[$this->fieldName()];
     }
     for ($i = 0; $i < count($values); ++$i) {
         // If the current value is selected or occurs in the record
         $sel = Tools::atk_in_array($values[$i], $recordvalue) ? 'selected' : '';
         $result .= '<option value="' . $values[$i] . '" ' . $sel . '>' . $this->_translateValue($values[$i], $record);
     }
     $result .= '</select>';
     $result .= "<script>ATK.enableSelect2ForSelect('#{$id}');</script>";
     return $result;
 }
开发者ID:sintattica,项目名称:atk,代码行数:52,代码来源:MultiSelectListAttribute.php


注:本文中的Sintattica\Atk\Core\Tools::atk_in_array方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。