diff --git a/framework/library/phpexcel/PHPExcel.php b/framework/library/phpexcel/PHPExcel.php new file mode 100644 index 0000000..abacb97 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel.php @@ -0,0 +1,895 @@ +_uniqueID = uniqid(); + $this->_calculationEngine = PHPExcel_Calculation::getInstance($this); + + // Initialise worksheet collection and add one worksheet + $this->_workSheetCollection = array(); + $this->_workSheetCollection[] = new PHPExcel_Worksheet($this); + $this->_activeSheetIndex = 0; + + // Create document properties + $this->_properties = new PHPExcel_DocumentProperties(); + + // Create document security + $this->_security = new PHPExcel_DocumentSecurity(); + + // Set named ranges + $this->_namedRanges = array(); + + // Create the cellXf supervisor + $this->_cellXfSupervisor = new PHPExcel_Style(true); + $this->_cellXfSupervisor->bindParent($this); + + // Create the default style + $this->addCellXf(new PHPExcel_Style); + $this->addCellStyleXf(new PHPExcel_Style); + } + + /** + * Code to execute when this worksheet is unset() + * + */ + public function __destruct() { + PHPExcel_Calculation::unsetInstance($this); + $this->disconnectWorksheets(); + } // function __destruct() + + /** + * Disconnect all worksheets from this PHPExcel workbook object, + * typically so that the PHPExcel object can be unset + * + */ + public function disconnectWorksheets() + { + $worksheet = NULL; + foreach($this->_workSheetCollection as $k => &$worksheet) { + $worksheet->disconnectCells(); + $this->_workSheetCollection[$k] = null; + } + unset($worksheet); + $this->_workSheetCollection = array(); + } + + /** + * Return the calculation engine for this worksheet + * + * @return PHPExcel_Calculation + */ + public function getCalculationEngine() + { + return $this->_calculationEngine; + } // function getCellCacheController() + + /** + * Get properties + * + * @return PHPExcel_DocumentProperties + */ + public function getProperties() + { + return $this->_properties; + } + + /** + * Set properties + * + * @param PHPExcel_DocumentProperties $pValue + */ + public function setProperties(PHPExcel_DocumentProperties $pValue) + { + $this->_properties = $pValue; + } + + /** + * Get security + * + * @return PHPExcel_DocumentSecurity + */ + public function getSecurity() + { + return $this->_security; + } + + /** + * Set security + * + * @param PHPExcel_DocumentSecurity $pValue + */ + public function setSecurity(PHPExcel_DocumentSecurity $pValue) + { + $this->_security = $pValue; + } + + /** + * Get active sheet + * + * @return PHPExcel_Worksheet + */ + public function getActiveSheet() + { + return $this->_workSheetCollection[$this->_activeSheetIndex]; + } + + /** + * Create sheet and add it to this workbook + * + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @return PHPExcel_Worksheet + * @throws PHPExcel_Exception + */ + public function createSheet($iSheetIndex = NULL) + { + $newSheet = new PHPExcel_Worksheet($this); + $this->addSheet($newSheet, $iSheetIndex); + return $newSheet; + } + + /** + * Check if a sheet with a specified name already exists + * + * @param string $pSheetName Name of the worksheet to check + * @return boolean + */ + public function sheetNameExists($pSheetName) + { + return ($this->getSheetByName($pSheetName) !== NULL); + } + + /** + * Add sheet + * + * @param PHPExcel_Worksheet $pSheet + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @return PHPExcel_Worksheet + * @throws PHPExcel_Exception + */ + public function addSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = NULL) + { + if ($this->sheetNameExists($pSheet->getTitle())) { + throw new PHPExcel_Exception( + "Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename this worksheet first." + ); + } + + if($iSheetIndex === NULL) { + if ($this->_activeSheetIndex < 0) { + $this->_activeSheetIndex = 0; + } + $this->_workSheetCollection[] = $pSheet; + } else { + // Insert the sheet at the requested index + array_splice( + $this->_workSheetCollection, + $iSheetIndex, + 0, + array($pSheet) + ); + + // Adjust active sheet index if necessary + if ($this->_activeSheetIndex >= $iSheetIndex) { + ++$this->_activeSheetIndex; + } + } + return $pSheet; + } + + /** + * Remove sheet by index + * + * @param int $pIndex Active sheet index + * @throws PHPExcel_Exception + */ + public function removeSheetByIndex($pIndex = 0) + { + + $numSheets = count($this->_workSheetCollection); + + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "You tried to remove a sheet by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}." + ); + } else { + array_splice($this->_workSheetCollection, $pIndex, 1); + } + // Adjust active sheet index if necessary + if (($this->_activeSheetIndex >= $pIndex) && + ($pIndex > count($this->_workSheetCollection) - 1)) { + --$this->_activeSheetIndex; + } + + } + + /** + * Get sheet by index + * + * @param int $pIndex Sheet index + * @return PHPExcel_Worksheet + * @throws PHPExcel_Exception + */ + public function getSheet($pIndex = 0) + { + + $numSheets = count($this->_workSheetCollection); + + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "Your requested sheet index: {$pIndex} is out of bounds. The actual number of sheets is {$numSheets}." + ); + } else { + return $this->_workSheetCollection[$pIndex]; + } + } + + /** + * Get all sheets + * + * @return PHPExcel_Worksheet[] + */ + public function getAllSheets() + { + return $this->_workSheetCollection; + } + + /** + * Get sheet by name + * + * @param string $pName Sheet name + * @return PHPExcel_Worksheet + */ + public function getSheetByName($pName = '') + { + $worksheetCount = count($this->_workSheetCollection); + for ($i = 0; $i < $worksheetCount; ++$i) { + if ($this->_workSheetCollection[$i]->getTitle() === $pName) { + return $this->_workSheetCollection[$i]; + } + } + + return NULL; + } + + /** + * Get index for sheet + * + * @param PHPExcel_Worksheet $pSheet + * @return Sheet index + * @throws PHPExcel_Exception + */ + public function getIndex(PHPExcel_Worksheet $pSheet) + { + foreach ($this->_workSheetCollection as $key => $value) { + if ($value->getHashCode() == $pSheet->getHashCode()) { + return $key; + } + } + + throw new PHPExcel_Exception("Sheet does not exist."); + } + + /** + * Set index for sheet by sheet name. + * + * @param string $sheetName Sheet name to modify index for + * @param int $newIndex New index for the sheet + * @return New sheet index + * @throws PHPExcel_Exception + */ + public function setIndexByName($sheetName, $newIndex) + { + $oldIndex = $this->getIndex($this->getSheetByName($sheetName)); + $pSheet = array_splice( + $this->_workSheetCollection, + $oldIndex, + 1 + ); + array_splice( + $this->_workSheetCollection, + $newIndex, + 0, + $pSheet + ); + return $newIndex; + } + + /** + * Get sheet count + * + * @return int + */ + public function getSheetCount() + { + return count($this->_workSheetCollection); + } + + /** + * Get active sheet index + * + * @return int Active sheet index + */ + public function getActiveSheetIndex() + { + return $this->_activeSheetIndex; + } + + /** + * Set active sheet index + * + * @param int $pIndex Active sheet index + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setActiveSheetIndex($pIndex = 0) + { + $numSheets = count($this->_workSheetCollection); + + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "You tried to set a sheet active by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}." + ); + } else { + $this->_activeSheetIndex = $pIndex; + } + return $this->getActiveSheet(); + } + + /** + * Set active sheet index by name + * + * @param string $pValue Sheet title + * @return PHPExcel_Worksheet + * @throws PHPExcel_Exception + */ + public function setActiveSheetIndexByName($pValue = '') + { + if (($worksheet = $this->getSheetByName($pValue)) instanceof PHPExcel_Worksheet) { + $this->setActiveSheetIndex($this->getIndex($worksheet)); + return $worksheet; + } + + throw new PHPExcel_Exception('Workbook does not contain sheet:' . $pValue); + } + + /** + * Get sheet names + * + * @return string[] + */ + public function getSheetNames() + { + $returnValue = array(); + $worksheetCount = $this->getSheetCount(); + for ($i = 0; $i < $worksheetCount; ++$i) { + $returnValue[] = $this->getSheet($i)->getTitle(); + } + + return $returnValue; + } + + /** + * Add external sheet + * + * @param PHPExcel_Worksheet $pSheet External sheet to add + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) { + if ($this->sheetNameExists($pSheet->getTitle())) { + throw new PHPExcel_Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first."); + } + + // count how many cellXfs there are in this workbook currently, we will need this below + $countCellXfs = count($this->_cellXfCollection); + + // copy all the shared cellXfs from the external workbook and append them to the current + foreach ($pSheet->getParent()->getCellXfCollection() as $cellXf) { + $this->addCellXf(clone $cellXf); + } + + // move sheet to this workbook + $pSheet->rebindParent($this); + + // update the cellXfs + foreach ($pSheet->getCellCollection(false) as $cellID) { + $cell = $pSheet->getCell($cellID); + $cell->setXfIndex( $cell->getXfIndex() + $countCellXfs ); + } + + return $this->addSheet($pSheet, $iSheetIndex); + } + + /** + * Get named ranges + * + * @return PHPExcel_NamedRange[] + */ + public function getNamedRanges() { + return $this->_namedRanges; + } + + /** + * Add named range + * + * @param PHPExcel_NamedRange $namedRange + * @return PHPExcel + */ + public function addNamedRange(PHPExcel_NamedRange $namedRange) { + if ($namedRange->getScope() == null) { + // global scope + $this->_namedRanges[$namedRange->getName()] = $namedRange; + } else { + // local scope + $this->_namedRanges[$namedRange->getScope()->getTitle().'!'.$namedRange->getName()] = $namedRange; + } + return true; + } + + /** + * Get named range + * + * @param string $namedRange + * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope + * @return PHPExcel_NamedRange|null + */ + public function getNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) { + $returnValue = null; + + if ($namedRange != '' && ($namedRange !== NULL)) { + // first look for global defined name + if (isset($this->_namedRanges[$namedRange])) { + $returnValue = $this->_namedRanges[$namedRange]; + } + + // then look for local defined name (has priority over global defined name if both names exist) + if (($pSheet !== NULL) && isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) { + $returnValue = $this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]; + } + } + + return $returnValue; + } + + /** + * Remove named range + * + * @param string $namedRange + * @param PHPExcel_Worksheet|null $pSheet Scope: use null for global scope. + * @return PHPExcel + */ + public function removeNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) { + if ($pSheet === NULL) { + if (isset($this->_namedRanges[$namedRange])) { + unset($this->_namedRanges[$namedRange]); + } + } else { + if (isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) { + unset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]); + } + } + return $this; + } + + /** + * Get worksheet iterator + * + * @return PHPExcel_WorksheetIterator + */ + public function getWorksheetIterator() { + return new PHPExcel_WorksheetIterator($this); + } + + /** + * Copy workbook (!= clone!) + * + * @return PHPExcel + */ + public function copy() { + $copied = clone $this; + + $worksheetCount = count($this->_workSheetCollection); + for ($i = 0; $i < $worksheetCount; ++$i) { + $this->_workSheetCollection[$i] = $this->_workSheetCollection[$i]->copy(); + $this->_workSheetCollection[$i]->rebindParent($this); + } + + return $copied; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + foreach($this as $key => $val) { + if (is_object($val) || (is_array($val))) { + $this->{$key} = unserialize(serialize($val)); + } + } + } + + /** + * Get the workbook collection of cellXfs + * + * @return PHPExcel_Style[] + */ + public function getCellXfCollection() + { + return $this->_cellXfCollection; + } + + /** + * Get cellXf by index + * + * @param int $pIndex + * @return PHPExcel_Style + */ + public function getCellXfByIndex($pIndex = 0) + { + return $this->_cellXfCollection[$pIndex]; + } + + /** + * Get cellXf by hash code + * + * @param string $pValue + * @return PHPExcel_Style|false + */ + public function getCellXfByHashCode($pValue = '') + { + foreach ($this->_cellXfCollection as $cellXf) { + if ($cellXf->getHashCode() == $pValue) { + return $cellXf; + } + } + return false; + } + + /** + * Check if style exists in style collection + * + * @param PHPExcel_Style $pCellStyle + * @return boolean + */ + public function cellXfExists($pCellStyle = null) + { + return in_array($pCellStyle, $this->_cellXfCollection, true); + } + + /** + * Get default style + * + * @return PHPExcel_Style + * @throws PHPExcel_Exception + */ + public function getDefaultStyle() + { + if (isset($this->_cellXfCollection[0])) { + return $this->_cellXfCollection[0]; + } + throw new PHPExcel_Exception('No default style found for this workbook'); + } + + /** + * Add a cellXf to the workbook + * + * @param PHPExcel_Style $style + */ + public function addCellXf(PHPExcel_Style $style) + { + $this->_cellXfCollection[] = $style; + $style->setIndex(count($this->_cellXfCollection) - 1); + } + + /** + * Remove cellXf by index. It is ensured that all cells get their xf index updated. + * + * @param int $pIndex Index to cellXf + * @throws PHPExcel_Exception + */ + public function removeCellXfByIndex($pIndex = 0) + { + if ($pIndex > count($this->_cellXfCollection) - 1) { + throw new PHPExcel_Exception("CellXf index is out of bounds."); + } else { + // first remove the cellXf + array_splice($this->_cellXfCollection, $pIndex, 1); + + // then update cellXf indexes for cells + foreach ($this->_workSheetCollection as $worksheet) { + foreach ($worksheet->getCellCollection(false) as $cellID) { + $cell = $worksheet->getCell($cellID); + $xfIndex = $cell->getXfIndex(); + if ($xfIndex > $pIndex ) { + // decrease xf index by 1 + $cell->setXfIndex($xfIndex - 1); + } else if ($xfIndex == $pIndex) { + // set to default xf index 0 + $cell->setXfIndex(0); + } + } + } + } + } + + /** + * Get the cellXf supervisor + * + * @return PHPExcel_Style + */ + public function getCellXfSupervisor() + { + return $this->_cellXfSupervisor; + } + + /** + * Get the workbook collection of cellStyleXfs + * + * @return PHPExcel_Style[] + */ + public function getCellStyleXfCollection() + { + return $this->_cellStyleXfCollection; + } + + /** + * Get cellStyleXf by index + * + * @param int $pIndex + * @return PHPExcel_Style + */ + public function getCellStyleXfByIndex($pIndex = 0) + { + return $this->_cellStyleXfCollection[$pIndex]; + } + + /** + * Get cellStyleXf by hash code + * + * @param string $pValue + * @return PHPExcel_Style|false + */ + public function getCellStyleXfByHashCode($pValue = '') + { + foreach ($this->_cellXfStyleCollection as $cellStyleXf) { + if ($cellStyleXf->getHashCode() == $pValue) { + return $cellStyleXf; + } + } + return false; + } + + /** + * Add a cellStyleXf to the workbook + * + * @param PHPExcel_Style $pStyle + */ + public function addCellStyleXf(PHPExcel_Style $pStyle) + { + $this->_cellStyleXfCollection[] = $pStyle; + $pStyle->setIndex(count($this->_cellStyleXfCollection) - 1); + } + + /** + * Remove cellStyleXf by index + * + * @param int $pIndex + * @throws PHPExcel_Exception + */ + public function removeCellStyleXfByIndex($pIndex = 0) + { + if ($pIndex > count($this->_cellStyleXfCollection) - 1) { + throw new PHPExcel_Exception("CellStyleXf index is out of bounds."); + } else { + array_splice($this->_cellStyleXfCollection, $pIndex, 1); + } + } + + /** + * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells + * and columns in the workbook + */ + public function garbageCollect() + { + // how many references are there to each cellXf ? + $countReferencesCellXf = array(); + foreach ($this->_cellXfCollection as $index => $cellXf) { + $countReferencesCellXf[$index] = 0; + } + + foreach ($this->getWorksheetIterator() as $sheet) { + + // from cells + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); + ++$countReferencesCellXf[$cell->getXfIndex()]; + } + + // from row dimensions + foreach ($sheet->getRowDimensions() as $rowDimension) { + if ($rowDimension->getXfIndex() !== null) { + ++$countReferencesCellXf[$rowDimension->getXfIndex()]; + } + } + + // from column dimensions + foreach ($sheet->getColumnDimensions() as $columnDimension) { + ++$countReferencesCellXf[$columnDimension->getXfIndex()]; + } + } + + // remove cellXfs without references and create mapping so we can update xfIndex + // for all cells and columns + $countNeededCellXfs = 0; + foreach ($this->_cellXfCollection as $index => $cellXf) { + if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf + ++$countNeededCellXfs; + } else { + unset($this->_cellXfCollection[$index]); + } + $map[$index] = $countNeededCellXfs - 1; + } + $this->_cellXfCollection = array_values($this->_cellXfCollection); + + // update the index for all cellXfs + foreach ($this->_cellXfCollection as $i => $cellXf) { + $cellXf->setIndex($i); + } + + // make sure there is always at least one cellXf (there should be) + if (empty($this->_cellXfCollection)) { + $this->_cellXfCollection[] = new PHPExcel_Style(); + } + + // update the xfIndex for all cells, row dimensions, column dimensions + foreach ($this->getWorksheetIterator() as $sheet) { + + // for all cells + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); + $cell->setXfIndex( $map[$cell->getXfIndex()] ); + } + + // for all row dimensions + foreach ($sheet->getRowDimensions() as $rowDimension) { + if ($rowDimension->getXfIndex() !== null) { + $rowDimension->setXfIndex( $map[$rowDimension->getXfIndex()] ); + } + } + + // for all column dimensions + foreach ($sheet->getColumnDimensions() as $columnDimension) { + $columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] ); + } + + // also do garbage collection for all the sheets + $sheet->garbageCollect(); + } + } + + /** + * Return the unique ID value assigned to this spreadsheet workbook + * + * @return string + */ + public function getID() { + return $this->_uniqueID; + } + +} diff --git a/framework/library/phpexcel/PHPExcel/NamedRange.php b/framework/library/phpexcel/PHPExcel/NamedRange.php new file mode 100644 index 0000000..9e7d41e --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/NamedRange.php @@ -0,0 +1,246 @@ +_worksheet) + * + * @var bool + */ + private $_localOnly; + + /** + * Scope + * + * @var PHPExcel_Worksheet + */ + private $_scope; + + /** + * Create a new NamedRange + * + * @param string $pName + * @param PHPExcel_Worksheet $pWorksheet + * @param string $pRange + * @param bool $pLocalOnly + * @param PHPExcel_Worksheet|null $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope. + * @throws PHPExcel_Exception + */ + public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null) + { + // Validate data + if (($pName === NULL) || ($pWorksheet === NULL) || ($pRange === NULL)) { + throw new PHPExcel_Exception('Parameters can not be null.'); + } + + // Set local members + $this->_name = $pName; + $this->_worksheet = $pWorksheet; + $this->_range = $pRange; + $this->_localOnly = $pLocalOnly; + $this->_scope = ($pLocalOnly == true) ? + (($pScope == null) ? $pWorksheet : $pScope) : null; + } + + /** + * Get name + * + * @return string + */ + public function getName() { + return $this->_name; + } + + /** + * Set name + * + * @param string $value + * @return PHPExcel_NamedRange + */ + public function setName($value = null) { + if ($value !== NULL) { + // Old title + $oldTitle = $this->_name; + + // Re-attach + if ($this->_worksheet !== NULL) { + $this->_worksheet->getParent()->removeNamedRange($this->_name,$this->_worksheet); + } + $this->_name = $value; + + if ($this->_worksheet !== NULL) { + $this->_worksheet->getParent()->addNamedRange($this); + } + + // New title + $newTitle = $this->_name; + PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_worksheet->getParent(), $oldTitle, $newTitle); + } + return $this; + } + + /** + * Get worksheet + * + * @return PHPExcel_Worksheet + */ + public function getWorksheet() { + return $this->_worksheet; + } + + /** + * Set worksheet + * + * @param PHPExcel_Worksheet $value + * @return PHPExcel_NamedRange + */ + public function setWorksheet(PHPExcel_Worksheet $value = null) { + if ($value !== NULL) { + $this->_worksheet = $value; + } + return $this; + } + + /** + * Get range + * + * @return string + */ + public function getRange() { + return $this->_range; + } + + /** + * Set range + * + * @param string $value + * @return PHPExcel_NamedRange + */ + public function setRange($value = null) { + if ($value !== NULL) { + $this->_range = $value; + } + return $this; + } + + /** + * Get localOnly + * + * @return bool + */ + public function getLocalOnly() { + return $this->_localOnly; + } + + /** + * Set localOnly + * + * @param bool $value + * @return PHPExcel_NamedRange + */ + public function setLocalOnly($value = false) { + $this->_localOnly = $value; + $this->_scope = $value ? $this->_worksheet : null; + return $this; + } + + /** + * Get scope + * + * @return PHPExcel_Worksheet|null + */ + public function getScope() { + return $this->_scope; + } + + /** + * Set scope + * + * @param PHPExcel_Worksheet|null $value + * @return PHPExcel_NamedRange + */ + public function setScope(PHPExcel_Worksheet $value = null) { + $this->_scope = $value; + $this->_localOnly = ($value == null) ? false : true; + return $this; + } + + /** + * Resolve a named range to a regular cell range + * + * @param string $pNamedRange Named range + * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope + * @return PHPExcel_NamedRange + */ + public static function resolveRange($pNamedRange = '', PHPExcel_Worksheet $pSheet) { + return $pSheet->getParent()->getNamedRange($pNamedRange, $pSheet); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/framework/library/phpexcel/PHPExcel/ReferenceHelper.php b/framework/library/phpexcel/PHPExcel/ReferenceHelper.php new file mode 100644 index 0000000..bf7771a --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/ReferenceHelper.php @@ -0,0 +1,918 @@ += ($beforeRow + $pNumRows)) && + ($cellRow < $beforeRow)) { + return TRUE; + } elseif ($pNumCols < 0 && + ($cellColumnIndex >= ($beforeColumnIndex + $pNumCols)) && + ($cellColumnIndex < $beforeColumnIndex)) { + return TRUE; + } + return FALSE; + } + + /** + * Update page breaks when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustPageBreaks(PHPExcel_Worksheet $pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aBreaks = $pSheet->getBreaks(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort')); + + foreach ($aBreaks as $key => $value) { + if (self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { + // If we're deleting, then clear any defined breaks that are within the range + // of rows/columns that we're deleting + $pSheet->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); + } else { + // Otherwise update any affected breaks by inserting a new break at the appropriate point + // and removing the old affected break + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setBreak($newReference, $value) + ->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); + } + } + } + } + + /** + * Update cell comments when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aComments = $pSheet->getComments(); + $aNewComments = array(); // the new array of all comments + + foreach ($aComments as $key => &$value) { + // Any comments inside a deleted range will be ignored + if (!self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { + // Otherwise build a new array of comments indexed by the adjusted cell reference + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + $aNewComments[$newReference] = $value; + } + } + // Replace the comments array with the new set of comments + $pSheet->setComments($aNewComments); + } + + /** + * Update hyperlinks when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aHyperlinkCollection = $pSheet->getHyperlinkCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort')); + + foreach ($aHyperlinkCollection as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setHyperlink( $newReference, $value ); + $pSheet->setHyperlink( $key, null ); + } + } + } + + /** + * Update data validations when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aDataValidationCollection = $pSheet->getDataValidationCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort')); + foreach ($aDataValidationCollection as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setDataValidation( $newReference, $value ); + $pSheet->setDataValidation( $key, null ); + } + } + } + + /** + * Update merged cells when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aMergeCells = $pSheet->getMergeCells(); + $aNewMergeCells = array(); // the new array of all merge cells + foreach ($aMergeCells as $key => &$value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + $aNewMergeCells[$newReference] = $newReference; + } + $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array + } + + /** + * Update protected cells when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aProtectedCells = $pSheet->getProtectedCells(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort')); + foreach ($aProtectedCells as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->protectCells( $newReference, $value, true ); + $pSheet->unprotectCells( $key ); + } + } + } + + /** + * Update column dimensions when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); + if (!empty($aColumnDimensions)) { + foreach ($aColumnDimensions as $objColumnDimension) { + $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows); + list($newReference) = PHPExcel_Cell::coordinateFromString($newReference); + if ($objColumnDimension->getColumnIndex() != $newReference) { + $objColumnDimension->setColumnIndex($newReference); + } + } + $pSheet->refreshColumnDimensions(); + } + } + + /** + * Update row dimensions when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); + if (!empty($aRowDimensions)) { + foreach ($aRowDimensions as $objRowDimension) { + $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows); + list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference); + if ($objRowDimension->getRowIndex() != $newReference) { + $objRowDimension->setRowIndex($newReference); + } + } + $pSheet->refreshRowDimensions(); + + $copyDimension = $pSheet->getRowDimension($beforeRow - 1); + for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) { + $newDimension = $pSheet->getRowDimension($i); + $newDimension->setRowHeight($copyDimension->getRowHeight()); + $newDimension->setVisible($copyDimension->getVisible()); + $newDimension->setOutlineLevel($copyDimension->getOutlineLevel()); + $newDimension->setCollapsed($copyDimension->getCollapsed()); + } + } + } + + /** + * Insert a new column or row, updating all possible related data + * + * @param string $pBefore Insert before this cell address (e.g. 'A1') + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @throws PHPExcel_Exception + */ + public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = NULL) + { + $remove = ($pNumCols < 0 || $pNumRows < 0); + $aCellCollection = $pSheet->getCellCollection(); + + // Get coordinates of $pBefore + $beforeColumn = 'A'; + $beforeRow = 1; + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString($pBefore); + $beforeColumnIndex = PHPExcel_Cell::columnIndexFromString($beforeColumn); + + // Clear cells if we are removing columns or rows + $highestColumn = $pSheet->getHighestColumn(); + $highestRow = $pSheet->getHighestRow(); + + // 1. Clear column strips if we are removing columns + if ($pNumCols < 0 && $beforeColumnIndex - 2 + $pNumCols > 0) { + for ($i = 1; $i <= $highestRow - 1; ++$i) { + for ($j = $beforeColumnIndex - 1 + $pNumCols; $j <= $beforeColumnIndex - 2; ++$j) { + $coordinate = PHPExcel_Cell::stringFromColumnIndex($j) . $i; + $pSheet->removeConditionalStyles($coordinate); + if ($pSheet->cellExists($coordinate)) { + $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); + $pSheet->getCell($coordinate)->setXfIndex(0); + } + } + } + } + + // 2. Clear row strips if we are removing rows + if ($pNumRows < 0 && $beforeRow - 1 + $pNumRows > 0) { + for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { + for ($j = $beforeRow + $pNumRows; $j <= $beforeRow - 1; ++$j) { + $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . $j; + $pSheet->removeConditionalStyles($coordinate); + if ($pSheet->cellExists($coordinate)) { + $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); + $pSheet->getCell($coordinate)->setXfIndex(0); + } + } + } + } + + // Loop through cells, bottom-up, and change cell coordinates + while (($cellID = $remove ? array_shift($aCellCollection) : array_pop($aCellCollection))) { + $cell = $pSheet->getCell($cellID); + $cellIndex = PHPExcel_Cell::columnIndexFromString($cell->getColumn()); + if ($cellIndex-1 + $pNumCols < 0) { + continue; + } + + // New coordinates + $newCoordinates = PHPExcel_Cell::stringFromColumnIndex($cellIndex-1 + $pNumCols) . ($cell->getRow() + $pNumRows); + + // Should the cell be updated? Move value and cellXf index from one cell to another. + if (($cellIndex >= $beforeColumnIndex) && + ($cell->getRow() >= $beforeRow)) { + + // Update cell styles + $pSheet->getCell($newCoordinates)->setXfIndex($cell->getXfIndex()); + + // Insert this cell at its new location + if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { + // Formula should be adjusted + $pSheet->getCell($newCoordinates) + ->setValue($this->updateFormulaReferences($cell->getValue(), + $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle())); + } else { + // Formula should not be adjusted + $pSheet->getCell($newCoordinates)->setValue($cell->getValue()); + } + + // Clear the original cell + $pSheet->getCellCacheController()->deleteCacheData($cellID); + + } else { + /* We don't need to update styles for rows/columns before our insertion position, + but we do still need to adjust any formulae in those cells */ + if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { + // Formula should be adjusted + $cell->setValue($this->updateFormulaReferences($cell->getValue(), + $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle())); + } + + } + } + + // Duplicate styles for the newly inserted cells + $highestColumn = $pSheet->getHighestColumn(); + $highestRow = $pSheet->getHighestRow(); + + if ($pNumCols > 0 && $beforeColumnIndex - 2 > 0) { + for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) { + + // Style + $coordinate = PHPExcel_Cell::stringFromColumnIndex( $beforeColumnIndex - 2 ) . $i; + if ($pSheet->cellExists($coordinate)) { + $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); + $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? + $pSheet->getConditionalStyles($coordinate) : false; + for ($j = $beforeColumnIndex - 1; $j <= $beforeColumnIndex - 2 + $pNumCols; ++$j) { + $pSheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex); + if ($conditionalStyles) { + $cloned = array(); + foreach ($conditionalStyles as $conditionalStyle) { + $cloned[] = clone $conditionalStyle; + } + $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($j) . $i, $cloned); + } + } + } + + } + } + + if ($pNumRows > 0 && $beforeRow - 1 > 0) { + for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { + + // Style + $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . ($beforeRow - 1); + if ($pSheet->cellExists($coordinate)) { + $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); + $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? + $pSheet->getConditionalStyles($coordinate) : false; + for ($j = $beforeRow; $j <= $beforeRow - 1 + $pNumRows; ++$j) { + $pSheet->getCell(PHPExcel_Cell::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex); + if ($conditionalStyles) { + $cloned = array(); + foreach ($conditionalStyles as $conditionalStyle) { + $cloned[] = clone $conditionalStyle; + } + $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($i) . $j, $cloned); + } + } + } + } + } + + // Update worksheet: column dimensions + $this->_adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: row dimensions + $this->_adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: page breaks + $this->_adjustPageBreaks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: comments + $this->_adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: hyperlinks + $this->_adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: data validations + $this->_adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: merge cells + $this->_adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: protected cells + $this->_adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: autofilter + $autoFilter = $pSheet->getAutoFilter(); + $autoFilterRange = $autoFilter->getRange(); + if (!empty($autoFilterRange)) { + if ($pNumCols != 0) { + $autoFilterColumns = array_keys($autoFilter->getColumns()); + if (count($autoFilterColumns) > 0) { + sscanf($pBefore,'%[A-Z]%d', $column, $row); + $columnIndex = PHPExcel_Cell::columnIndexFromString($column); + list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($autoFilterRange); + if ($columnIndex <= $rangeEnd[0]) { + if ($pNumCols < 0) { + // If we're actually deleting any columns that fall within the autofilter range, + // then we delete any rules for those columns + $deleteColumn = $columnIndex + $pNumCols - 1; + $deleteCount = abs($pNumCols); + for ($i = 1; $i <= $deleteCount; ++$i) { + if (in_array(PHPExcel_Cell::stringFromColumnIndex($deleteColumn),$autoFilterColumns)) { + $autoFilter->clearColumn(PHPExcel_Cell::stringFromColumnIndex($deleteColumn)); + } + ++$deleteColumn; + } + } + $startCol = ($columnIndex > $rangeStart[0]) ? $columnIndex : $rangeStart[0]; + + // Shuffle columns in autofilter range + if ($pNumCols > 0) { + // For insert, we shuffle from end to beginning to avoid overwriting + $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1); + $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); + + $startColRef = $startCol; + $endColRef = $rangeEnd[0]; + $toColRef = $rangeEnd[0]+$pNumCols; + + do { + $autoFilter->shiftColumn(PHPExcel_Cell::stringFromColumnIndex($endColRef-1),PHPExcel_Cell::stringFromColumnIndex($toColRef-1)); + --$endColRef; + --$toColRef; + } while ($startColRef <= $endColRef); + } else { + // For delete, we shuffle from beginning to end to avoid overwriting + $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1); + $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); + do { + $autoFilter->shiftColumn($startColID,$toColID); + ++$startColID; + ++$toColID; + } while ($startColID != $endColID); + } + } + } + } + $pSheet->setAutoFilter( $this->updateCellReference($autoFilterRange, $pBefore, $pNumCols, $pNumRows) ); + } + + // Update worksheet: freeze pane + if ($pSheet->getFreezePane() != '') { + $pSheet->freezePane( $this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows) ); + } + + // Page setup + if ($pSheet->getPageSetup()->isPrintAreaSet()) { + $pSheet->getPageSetup()->setPrintArea( $this->updateCellReference($pSheet->getPageSetup()->getPrintArea(), $pBefore, $pNumCols, $pNumRows) ); + } + + // Update worksheet: drawings + $aDrawings = $pSheet->getDrawingCollection(); + foreach ($aDrawings as $objDrawing) { + $newReference = $this->updateCellReference($objDrawing->getCoordinates(), $pBefore, $pNumCols, $pNumRows); + if ($objDrawing->getCoordinates() != $newReference) { + $objDrawing->setCoordinates($newReference); + } + } + + // Update workbook: named ranges + if (count($pSheet->getParent()->getNamedRanges()) > 0) { + foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) { + if ($namedRange->getWorksheet()->getHashCode() == $pSheet->getHashCode()) { + $namedRange->setRange( + $this->updateCellReference($namedRange->getRange(), $pBefore, $pNumCols, $pNumRows) + ); + } + } + } + + // Garbage collect + $pSheet->garbageCollect(); + } + + /** + * Update references within formulas + * + * @param string $pFormula Formula to update + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to insert + * @param int $pNumRows Number of rows to insert + * @param string $sheetName Worksheet name/title + * @return string Updated formula + * @throws PHPExcel_Exception + */ + public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, $sheetName = '') { + // Update cell references in the formula + $formulaBlocks = explode('"',$pFormula); + $i = false; + foreach($formulaBlocks as &$formulaBlock) { + // Ignore blocks that were enclosed in quotes (alternating entries in the $formulaBlocks array after the explode) + if ($i = !$i) { + $adjustCount = 0; + $newCellTokens = $cellTokens = array(); + // Search for row ranges (e.g. 'Sheet1'!3:5 or 3:5) with or without $ absolutes (e.g. $3:5) + $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_ROWRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); + if ($matchCount > 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3].':'.$match[4]; + $modified3 = substr($this->updateCellReference('$A'.$match[3],$pBefore,$pNumCols,$pNumRows),2); + $modified4 = substr($this->updateCellReference('$A'.$match[4],$pBefore,$pNumCols,$pNumRows),2); + + if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3.':'.$modified4; + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = 100000; + $row = 10000000+trim($match[3],'$'); + $cellIndex = $column.$row; + + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(? 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3].':'.$match[4]; + $modified3 = substr($this->updateCellReference($match[3].'$1',$pBefore,$pNumCols,$pNumRows),0,-2); + $modified4 = substr($this->updateCellReference($match[4].'$1',$pBefore,$pNumCols,$pNumRows),0,-2); + + if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3.':'.$modified4; + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = PHPExcel_Cell::columnIndexFromString(trim($match[3],'$')) + 100000; + $row = 10000000; + $cellIndex = $column.$row; + + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(? 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3].':'.$match[4]; + $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows); + $modified4 = $this->updateCellReference($match[4],$pBefore,$pNumCols,$pNumRows); + + if ($match[3].$match[4] !== $modified3.$modified4) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3.':'.$modified4; + list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]); + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000; + $row = trim($row,'$') + 10000000; + $cellIndex = $column.$row; + + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(? 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3]; + $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows); + + if ($match[3] !== $modified3) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3; + list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]); + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000; + $row = trim($row,'$') + 10000000; + $cellIndex = $column.$row; + + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(? 0) { + if ($pNumCols > 0) { + krsort($cellTokens); + krsort($newCellTokens); + } else { + ksort($cellTokens); + ksort($newCellTokens); + } + // Update cell references in the formula + $formulaBlock = str_replace('\\','',preg_replace($cellTokens,$newCellTokens,$formulaBlock)); + } + } + } + unset($formulaBlock); + + // Then rebuild the formula string + return implode('"',$formulaBlocks); + } + + /** + * Update cell reference + * + * @param string $pCellRange Cell range + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell range + * @throws PHPExcel_Exception + */ + public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + // Is it in another worksheet? Will not have to update anything. + if (strpos($pCellRange, "!") !== false) { + return $pCellRange; + // Is it a range or a single cell? + } elseif (strpos($pCellRange, ':') === false && strpos($pCellRange, ',') === false) { + // Single cell + return $this->_updateSingleCellReference($pCellRange, $pBefore, $pNumCols, $pNumRows); + } elseif (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) { + // Range + return $this->_updateCellRange($pCellRange, $pBefore, $pNumCols, $pNumRows); + } else { + // Return original + return $pCellRange; + } + } + + /** + * Update named formulas (i.e. containing worksheet references / named ranges) + * + * @param PHPExcel $pPhpExcel Object to update + * @param string $oldName Old name (name to replace) + * @param string $newName New name + */ + public function updateNamedFormulas(PHPExcel $pPhpExcel, $oldName = '', $newName = '') { + if ($oldName == '') { + return; + } + + foreach ($pPhpExcel->getWorksheetIterator() as $sheet) { + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); + if (($cell !== NULL) && ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA)) { + $formula = $cell->getValue(); + if (strpos($formula, $oldName) !== false) { + $formula = str_replace("'" . $oldName . "'!", "'" . $newName . "'!", $formula); + $formula = str_replace($oldName . "!", $newName . "!", $formula); + $cell->setValueExplicit($formula, PHPExcel_Cell_DataType::TYPE_FORMULA); + } + } + } + } + } + + /** + * Update cell range + * + * @param string $pCellRange Cell range (e.g. 'B2:D4', 'B:C' or '2:3') + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell range + * @throws PHPExcel_Exception + */ + private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) { + // Update range + $range = PHPExcel_Cell::splitRange($pCellRange); + $ic = count($range); + for ($i = 0; $i < $ic; ++$i) { + $jc = count($range[$i]); + for ($j = 0; $j < $jc; ++$j) { + if (ctype_alpha($range[$i][$j])) { + $r = PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference($range[$i][$j].'1', $pBefore, $pNumCols, $pNumRows)); + $range[$i][$j] = $r[0]; + } elseif(ctype_digit($range[$i][$j])) { + $r = PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference('A'.$range[$i][$j], $pBefore, $pNumCols, $pNumRows)); + $range[$i][$j] = $r[1]; + } else { + $range[$i][$j] = $this->_updateSingleCellReference($range[$i][$j], $pBefore, $pNumCols, $pNumRows); + } + } + } + + // Recreate range string + return PHPExcel_Cell::buildRange($range); + } else { + throw new PHPExcel_Exception("Only cell ranges may be passed to this method."); + } + } + + /** + * Update single cell reference + * + * @param string $pCellReference Single cell reference + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell reference + * @throws PHPExcel_Exception + */ + private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) { + // Get coordinates of $pBefore + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); + + // Get coordinates of $pCellReference + list($newColumn, $newRow) = PHPExcel_Cell::coordinateFromString( $pCellReference ); + + // Verify which parts should be updated + $updateColumn = (($newColumn{0} != '$') && ($beforeColumn{0} != '$') && + PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)); + + $updateRow = (($newRow{0} != '$') && ($beforeRow{0} != '$') && + $newRow >= $beforeRow); + + // Create new column reference + if ($updateColumn) { + $newColumn = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($newColumn) - 1 + $pNumCols ); + } + + // Create new row reference + if ($updateRow) { + $newRow = $newRow + $pNumRows; + } + + // Return new reference + return $newColumn . $newRow; + } else { + throw new PHPExcel_Exception("Only single cell references may be passed to this method."); + } + } + + /** + * __clone implementation. Cloning should not be allowed in a Singleton! + * + * @throws PHPExcel_Exception + */ + public final function __clone() { + throw new PHPExcel_Exception("Cloning a Singleton is not allowed!"); + } +} diff --git a/framework/library/phpexcel/PHPExcel/Style/NumberFormat.php b/framework/library/phpexcel/PHPExcel/Style/NumberFormat.php new file mode 100644 index 0000000..a381f4f --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Style/NumberFormat.php @@ -0,0 +1,708 @@ +_formatCode = NULL; + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_NumberFormat + */ + public function getSharedComponent() + { + return $this->_parent->getSharedComponent()->getNumberFormat(); + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + return array('numberformat' => $array); + } + + /** + * Apply styles from array + * + * + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getNumberFormat()->applyFromArray( + * array( + * 'code' => PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE + * ) + * ); + * + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_NumberFormat + */ + public function applyFromArray($pStyles = null) + { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (array_key_exists('code', $pStyles)) { + $this->setFormatCode($pStyles['code']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get Format Code + * + * @return string + */ + public function getFormatCode() + { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getFormatCode(); + } + if ($this->_builtInFormatCode !== false) + { + return self::builtInFormatCode($this->_builtInFormatCode); + } + return $this->_formatCode; + } + + /** + * Set Format Code + * + * @param string $pValue + * @return PHPExcel_Style_NumberFormat + */ + public function setFormatCode($pValue = PHPExcel_Style_NumberFormat::FORMAT_GENERAL) + { + if ($pValue == '') { + $pValue = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('code' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_formatCode = $pValue; + $this->_builtInFormatCode = self::builtInFormatCodeIndex($pValue); + } + return $this; + } + + /** + * Get Built-In Format Code + * + * @return int + */ + public function getBuiltInFormatCode() + { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getBuiltInFormatCode(); + } + return $this->_builtInFormatCode; + } + + /** + * Set Built-In Format Code + * + * @param int $pValue + * @return PHPExcel_Style_NumberFormat + */ + public function setBuiltInFormatCode($pValue = 0) + { + + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('code' => self::builtInFormatCode($pValue))); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_builtInFormatCode = $pValue; + $this->_formatCode = self::builtInFormatCode($pValue); + } + return $this; + } + + /** + * Fill built-in format codes + */ + private static function fillBuiltInFormatCodes() + { + // Built-in format codes + if (is_null(self::$_builtInFormats)) { + self::$_builtInFormats = array(); + + // General + self::$_builtInFormats[0] = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + self::$_builtInFormats[1] = '0'; + self::$_builtInFormats[2] = '0.00'; + self::$_builtInFormats[3] = '#,##0'; + self::$_builtInFormats[4] = '#,##0.00'; + + self::$_builtInFormats[9] = '0%'; + self::$_builtInFormats[10] = '0.00%'; + self::$_builtInFormats[11] = '0.00E+00'; + self::$_builtInFormats[12] = '# ?/?'; + self::$_builtInFormats[13] = '# ??/??'; + self::$_builtInFormats[14] = 'mm-dd-yy'; + self::$_builtInFormats[15] = 'd-mmm-yy'; + self::$_builtInFormats[16] = 'd-mmm'; + self::$_builtInFormats[17] = 'mmm-yy'; + self::$_builtInFormats[18] = 'h:mm AM/PM'; + self::$_builtInFormats[19] = 'h:mm:ss AM/PM'; + self::$_builtInFormats[20] = 'h:mm'; + self::$_builtInFormats[21] = 'h:mm:ss'; + self::$_builtInFormats[22] = 'm/d/yy h:mm'; + + self::$_builtInFormats[37] = '#,##0 ;(#,##0)'; + self::$_builtInFormats[38] = '#,##0 ;[Red](#,##0)'; + self::$_builtInFormats[39] = '#,##0.00;(#,##0.00)'; + self::$_builtInFormats[40] = '#,##0.00;[Red](#,##0.00)'; + + self::$_builtInFormats[44] = '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)'; + self::$_builtInFormats[45] = 'mm:ss'; + self::$_builtInFormats[46] = '[h]:mm:ss'; + self::$_builtInFormats[47] = 'mmss.0'; + self::$_builtInFormats[48] = '##0.0E+0'; + self::$_builtInFormats[49] = '@'; + + // CHT + self::$_builtInFormats[27] = '[$-404]e/m/d'; + self::$_builtInFormats[30] = 'm/d/yy'; + self::$_builtInFormats[36] = '[$-404]e/m/d'; + self::$_builtInFormats[50] = '[$-404]e/m/d'; + self::$_builtInFormats[57] = '[$-404]e/m/d'; + + // THA + self::$_builtInFormats[59] = 't0'; + self::$_builtInFormats[60] = 't0.00'; + self::$_builtInFormats[61] = 't#,##0'; + self::$_builtInFormats[62] = 't#,##0.00'; + self::$_builtInFormats[67] = 't0%'; + self::$_builtInFormats[68] = 't0.00%'; + self::$_builtInFormats[69] = 't# ?/?'; + self::$_builtInFormats[70] = 't# ??/??'; + + // Flip array (for faster lookups) + self::$_flippedBuiltInFormats = array_flip(self::$_builtInFormats); + } + } + + /** + * Get built-in format code + * + * @param int $pIndex + * @return string + */ + public static function builtInFormatCode($pIndex) + { + // Clean parameter + $pIndex = intval($pIndex); + + // Ensure built-in format codes are available + self::fillBuiltInFormatCodes(); + + // Lookup format code + if (isset(self::$_builtInFormats[$pIndex])) { + return self::$_builtInFormats[$pIndex]; + } + + return ''; + } + + /** + * Get built-in format code index + * + * @param string $formatCode + * @return int|boolean + */ + public static function builtInFormatCodeIndex($formatCode) + { + // Ensure built-in format codes are available + self::fillBuiltInFormatCodes(); + + // Lookup format code + if (isset(self::$_flippedBuiltInFormats[$formatCode])) { + return self::$_flippedBuiltInFormats[$formatCode]; + } + + return false; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() + { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->_formatCode + . $this->_builtInFormatCode + . __CLASS__ + ); + } + + /** + * Search/replace values to convert Excel date/time format masks to PHP format masks + * + * @var array + */ + private static $_dateFormatReplacements = array( + // first remove escapes related to non-format characters + '\\' => '', + // 12-hour suffix + 'am/pm' => 'A', + // 4-digit year + 'e' => 'Y', + 'yyyy' => 'Y', + // 2-digit year + 'yy' => 'y', + // first letter of month - no php equivalent + 'mmmmm' => 'M', + // full month name + 'mmmm' => 'F', + // short month name + 'mmm' => 'M', + // mm is minutes if time, but can also be month w/leading zero + // so we try to identify times be the inclusion of a : separator in the mask + // It isn't perfect, but the best way I know how + ':mm' => ':i', + 'mm:' => 'i:', + // month leading zero + 'mm' => 'm', + // month no leading zero + 'm' => 'n', + // full day of week name + 'dddd' => 'l', + // short day of week name + 'ddd' => 'D', + // days leading zero + 'dd' => 'd', + // days no leading zero + 'd' => 'j', + // seconds + 'ss' => 's', + // fractional seconds - no php equivalent + '.s' => '' + ); + /** + * Search/replace values to convert Excel date/time format masks hours to PHP format masks (24 hr clock) + * + * @var array + */ + private static $_dateFormatReplacements24 = array( + 'hh' => 'H', + 'h' => 'G' + ); + /** + * Search/replace values to convert Excel date/time format masks hours to PHP format masks (12 hr clock) + * + * @var array + */ + private static $_dateFormatReplacements12 = array( + 'hh' => 'h', + 'h' => 'g' + ); + + private static function _formatAsDate(&$value, &$format) + { + // dvc: convert Excel formats to PHP date formats + + // strip off first part containing e.g. [$-F800] or [$USD-409] + // general syntax: [$-] + // language info is in hexadecimal + $format = preg_replace('/^(\[\$[A-Z]*-[0-9A-F]*\])/i', '', $format); + + // OpenOffice.org uses upper-case number formats, e.g. 'YYYY', convert to lower-case + $format = strtolower($format); + + $format = strtr($format,self::$_dateFormatReplacements); + if (!strpos($format,'A')) { // 24-hour time format + $format = strtr($format,self::$_dateFormatReplacements24); + } else { // 12-hour time format + $format = strtr($format,self::$_dateFormatReplacements12); + } + + $dateObj = PHPExcel_Shared_Date::ExcelToPHPObject($value); + $value = $dateObj->format($format); + } + + private static function _formatAsPercentage(&$value, &$format) + { + if ($format === self::FORMAT_PERCENTAGE) { + $value = round( (100 * $value), 0) . '%'; + } else { + if (preg_match('/\.[#0]+/i', $format, $m)) { + $s = substr($m[0], 0, 1) . (strlen($m[0]) - 1); + $format = str_replace($m[0], $s, $format); + } + if (preg_match('/^[#0]+/', $format, $m)) { + $format = str_replace($m[0], strlen($m[0]), $format); + } + $format = '%' . str_replace('%', 'f%%', $format); + + $value = sprintf($format, 100 * $value); + } + } + + private static function _formatAsFraction(&$value, &$format) + { + $sign = ($value < 0) ? '-' : ''; + + $integerPart = floor(abs($value)); + $decimalPart = trim(fmod(abs($value),1),'0.'); + $decimalLength = strlen($decimalPart); + $decimalDivisor = pow(10,$decimalLength); + + $GCD = PHPExcel_Calculation_MathTrig::GCD($decimalPart,$decimalDivisor); + + $adjustedDecimalPart = $decimalPart/$GCD; + $adjustedDecimalDivisor = $decimalDivisor/$GCD; + + if ((strpos($format,'0') !== false) || (strpos($format,'#') !== false) || (substr($format,0,3) == '? ?')) { + if ($integerPart == 0) { + $integerPart = ''; + } + $value = "$sign$integerPart $adjustedDecimalPart/$adjustedDecimalDivisor"; + } else { + $adjustedDecimalPart += $integerPart * $adjustedDecimalDivisor; + $value = "$sign$adjustedDecimalPart/$adjustedDecimalDivisor"; + } + } + + private static function _complexNumberFormatMask($number, $mask) { + if (strpos($mask,'.') !== false) { + $numbers = explode('.', $number . '.0'); + $masks = explode('.', $mask . '.0'); + $result1 = self::_complexNumberFormatMask($numbers[0], $masks[0]); + $result2 = strrev(self::_complexNumberFormatMask(strrev($numbers[1]), strrev($masks[1]))); + return $result1 . '.' . $result2; + } + + $r = preg_match_all('/0+/', $mask, $result, PREG_OFFSET_CAPTURE); + if ($r > 1) { + $result = array_reverse($result[0]); + + foreach($result as $block) { + $divisor = 1 . $block[0]; + $size = strlen($block[0]); + $offset = $block[1]; + + $blockValue = sprintf( + '%0' . $size . 'd', + fmod($number, $divisor) + ); + $number = floor($number / $divisor); + $mask = substr_replace($mask,$blockValue, $offset, $size); + } + if ($number > 0) { + $mask = substr_replace($mask, $number, $offset, 0); + } + $result = $mask; + } else { + $result = $number; + } + + return $result; + } + + /** + * Convert a value in a pre-defined format to a PHP string + * + * @param mixed $value Value to format + * @param string $format Format code + * @param array $callBack Callback function for additional formatting of string + * @return string Formatted string + */ + public static function toFormattedString($value = '0', $format = PHPExcel_Style_NumberFormat::FORMAT_GENERAL, $callBack = null) + { + // For now we do not treat strings although section 4 of a format code affects strings + if (!is_numeric($value)) return $value; + + // For 'General' format code, we just pass the value although this is not entirely the way Excel does it, + // it seems to round numbers to a total of 10 digits. + if (($format === PHPExcel_Style_NumberFormat::FORMAT_GENERAL) || ($format === PHPExcel_Style_NumberFormat::FORMAT_TEXT)) { + return $value; + } + + // Get the sections, there can be up to four sections + $sections = explode(';', $format); + + // Fetch the relevant section depending on whether number is positive, negative, or zero? + // Text not supported yet. + // Here is how the sections apply to various values in Excel: + // 1 section: [POSITIVE/NEGATIVE/ZERO/TEXT] + // 2 sections: [POSITIVE/ZERO/TEXT] [NEGATIVE] + // 3 sections: [POSITIVE/TEXT] [NEGATIVE] [ZERO] + // 4 sections: [POSITIVE] [NEGATIVE] [ZERO] [TEXT] + switch (count($sections)) { + case 1: + $format = $sections[0]; + break; + + case 2: + $format = ($value >= 0) ? $sections[0] : $sections[1]; + $value = abs($value); // Use the absolute value + break; + + case 3: + $format = ($value > 0) ? + $sections[0] : ( ($value < 0) ? + $sections[1] : $sections[2]); + $value = abs($value); // Use the absolute value + break; + + case 4: + $format = ($value > 0) ? + $sections[0] : ( ($value < 0) ? + $sections[1] : $sections[2]); + $value = abs($value); // Use the absolute value + break; + + default: + // something is wrong, just use first section + $format = $sections[0]; + break; + } + + // Save format with color information for later use below + $formatColor = $format; + + // Strip color information + $color_regex = '/^\\[[a-zA-Z]+\\]/'; + $format = preg_replace($color_regex, '', $format); + + // Let's begin inspecting the format and converting the value to a formatted string + if (preg_match('/^(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy]/i', $format)) { // datetime format + self::_formatAsDate($value, $format); + } else if (preg_match('/%$/', $format)) { // % number format + self::_formatAsPercentage($value, $format); + } else { + if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) { + $value = 'EUR ' . sprintf('%1.2f', $value); + } else { + // In Excel formats, "_" is used to add spacing, which we can't do in HTML + $format = preg_replace('/_./', '', $format); + + // Some non-number characters are escaped with \, which we don't need + $format = preg_replace("/\\\\/", '', $format); + + // Some non-number strings are quoted, so we'll get rid of the quotes, likewise any positional * symbols + $format = str_replace(array('"','*'), '', $format); + + // Find out if we need thousands separator + // This is indicated by a comma enclosed by a digit placeholder: + // #,# or 0,0 + $useThousands = preg_match('/(#,#|0,0)/', $format); + if ($useThousands) { + $format = preg_replace('/0,0/', '00', $format); + $format = preg_replace('/#,#/', '##', $format); + } + + // Scale thousands, millions,... + // This is indicated by a number of commas after a digit placeholder: + // #, or 0.0,, + $scale = 1; // same as no scale + $matches = array(); + if (preg_match('/(#|0)(,+)/', $format, $matches)) { + $scale = pow(1000, strlen($matches[2])); + + // strip the commas + $format = preg_replace('/0,+/', '0', $format); + $format = preg_replace('/#,+/', '#', $format); + } + + if (preg_match('/#?.*\?\/\?/', $format, $m)) { + //echo 'Format mask is fractional '.$format.'
'; + if ($value != (int)$value) { + self::_formatAsFraction($value, $format); + } + + } else { + // Handle the number itself + + // scale number + $value = $value / $scale; + + // Strip # + $format = preg_replace('/\\#/', '0', $format); + + $n = "/\[[^\]]+\]/"; + $m = preg_replace($n, '', $format); + $number_regex = "/(0+)(\.?)(0*)/"; + if (preg_match($number_regex, $m, $matches)) { + $left = $matches[1]; + $dec = $matches[2]; + $right = $matches[3]; + + // minimun width of formatted number (including dot) + $minWidth = strlen($left) + strlen($dec) + strlen($right); + if ($useThousands) { + $value = number_format( + $value + , strlen($right) + , PHPExcel_Shared_String::getDecimalSeparator() + , PHPExcel_Shared_String::getThousandsSeparator() + ); + $value = preg_replace($number_regex, $value, $format); + } else { + if (preg_match('/0([^\d\.]+)0/', $format, $matches)) { + $value = self::_complexNumberFormatMask($value, $format); + } else { + $sprintf_pattern = "%0$minWidth." . strlen($right) . "f"; + $value = sprintf($sprintf_pattern, $value); + $value = preg_replace($number_regex, $value, $format); + } + } + } + } + if (preg_match('/\[\$(.*)\]/u', $format, $m)) { + // Currency or Accounting + $currencyFormat = $m[0]; + $currencyCode = $m[1]; + list($currencyCode) = explode('-',$currencyCode); + if ($currencyCode == '') { + $currencyCode = PHPExcel_Shared_String::getCurrencyCode(); + } + $value = preg_replace('/\[\$([^\]]*)\]/u',$currencyCode,$value); + } + } + } + + // Additional formatting provided by callback function + if ($callBack !== null) { + list($writerInstance, $function) = $callBack; + $value = $writerInstance->$function($value, $formatColor); + } + + return $value; + } + +} diff --git a/framework/library/phpexcel/PHPExcel/Style/Protection.php b/framework/library/phpexcel/PHPExcel/Style/Protection.php new file mode 100644 index 0000000..a8f65ce --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Style/Protection.php @@ -0,0 +1,207 @@ +_locked = self::PROTECTION_INHERIT; + $this->_hidden = self::PROTECTION_INHERIT; + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_Protection + */ + public function getSharedComponent() + { + return $this->_parent->getSharedComponent()->getProtection(); + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + return array('protection' => $array); + } + + /** + * Apply styles from array + * + * + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getLocked()->applyFromArray( + * array( + * 'locked' => TRUE, + * 'hidden' => FALSE + * ) + * ); + * + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Protection + */ + public function applyFromArray($pStyles = NULL) { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (isset($pStyles['locked'])) { + $this->setLocked($pStyles['locked']); + } + if (isset($pStyles['hidden'])) { + $this->setHidden($pStyles['hidden']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get locked + * + * @return string + */ + public function getLocked() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getLocked(); + } + return $this->_locked; + } + + /** + * Set locked + * + * @param string $pValue + * @return PHPExcel_Style_Protection + */ + public function setLocked($pValue = self::PROTECTION_INHERIT) { + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('locked' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_locked = $pValue; + } + return $this; + } + + /** + * Get hidden + * + * @return string + */ + public function getHidden() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHidden(); + } + return $this->_hidden; + } + + /** + * Set hidden + * + * @param string $pValue + * @return PHPExcel_Style_Protection + */ + public function setHidden($pValue = self::PROTECTION_INHERIT) { + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('hidden' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_hidden = $pValue; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->_locked + . $this->_hidden + . __CLASS__ + ); + } + +} diff --git a/framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php b/framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php new file mode 100644 index 0000000..339815d --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php @@ -0,0 +1,220 @@ +_left; + } + + /** + * Set Left + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setLeft($pValue) { + $this->_left = $pValue; + return $this; + } + + /** + * Get Right + * + * @return double + */ + public function getRight() { + return $this->_right; + } + + /** + * Set Right + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setRight($pValue) { + $this->_right = $pValue; + return $this; + } + + /** + * Get Top + * + * @return double + */ + public function getTop() { + return $this->_top; + } + + /** + * Set Top + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setTop($pValue) { + $this->_top = $pValue; + return $this; + } + + /** + * Get Bottom + * + * @return double + */ + public function getBottom() { + return $this->_bottom; + } + + /** + * Set Bottom + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setBottom($pValue) { + $this->_bottom = $pValue; + return $this; + } + + /** + * Get Header + * + * @return double + */ + public function getHeader() { + return $this->_header; + } + + /** + * Set Header + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setHeader($pValue) { + $this->_header = $pValue; + return $this; + } + + /** + * Get Footer + * + * @return double + */ + public function getFooter() { + return $this->_footer; + } + + /** + * Set Footer + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setFooter($pValue) { + $this->_footer = $pValue; + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php b/framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php new file mode 100644 index 0000000..1508eea --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php @@ -0,0 +1,798 @@ + + * Paper size taken from Office Open XML Part 4 - Markup Language Reference, page 1988: + * + * 1 = Letter paper (8.5 in. by 11 in.) + * 2 = Letter small paper (8.5 in. by 11 in.) + * 3 = Tabloid paper (11 in. by 17 in.) + * 4 = Ledger paper (17 in. by 11 in.) + * 5 = Legal paper (8.5 in. by 14 in.) + * 6 = Statement paper (5.5 in. by 8.5 in.) + * 7 = Executive paper (7.25 in. by 10.5 in.) + * 8 = A3 paper (297 mm by 420 mm) + * 9 = A4 paper (210 mm by 297 mm) + * 10 = A4 small paper (210 mm by 297 mm) + * 11 = A5 paper (148 mm by 210 mm) + * 12 = B4 paper (250 mm by 353 mm) + * 13 = B5 paper (176 mm by 250 mm) + * 14 = Folio paper (8.5 in. by 13 in.) + * 15 = Quarto paper (215 mm by 275 mm) + * 16 = Standard paper (10 in. by 14 in.) + * 17 = Standard paper (11 in. by 17 in.) + * 18 = Note paper (8.5 in. by 11 in.) + * 19 = #9 envelope (3.875 in. by 8.875 in.) + * 20 = #10 envelope (4.125 in. by 9.5 in.) + * 21 = #11 envelope (4.5 in. by 10.375 in.) + * 22 = #12 envelope (4.75 in. by 11 in.) + * 23 = #14 envelope (5 in. by 11.5 in.) + * 24 = C paper (17 in. by 22 in.) + * 25 = D paper (22 in. by 34 in.) + * 26 = E paper (34 in. by 44 in.) + * 27 = DL envelope (110 mm by 220 mm) + * 28 = C5 envelope (162 mm by 229 mm) + * 29 = C3 envelope (324 mm by 458 mm) + * 30 = C4 envelope (229 mm by 324 mm) + * 31 = C6 envelope (114 mm by 162 mm) + * 32 = C65 envelope (114 mm by 229 mm) + * 33 = B4 envelope (250 mm by 353 mm) + * 34 = B5 envelope (176 mm by 250 mm) + * 35 = B6 envelope (176 mm by 125 mm) + * 36 = Italy envelope (110 mm by 230 mm) + * 37 = Monarch envelope (3.875 in. by 7.5 in.). + * 38 = 6 3/4 envelope (3.625 in. by 6.5 in.) + * 39 = US standard fanfold (14.875 in. by 11 in.) + * 40 = German standard fanfold (8.5 in. by 12 in.) + * 41 = German legal fanfold (8.5 in. by 13 in.) + * 42 = ISO B4 (250 mm by 353 mm) + * 43 = Japanese double postcard (200 mm by 148 mm) + * 44 = Standard paper (9 in. by 11 in.) + * 45 = Standard paper (10 in. by 11 in.) + * 46 = Standard paper (15 in. by 11 in.) + * 47 = Invite envelope (220 mm by 220 mm) + * 50 = Letter extra paper (9.275 in. by 12 in.) + * 51 = Legal extra paper (9.275 in. by 15 in.) + * 52 = Tabloid extra paper (11.69 in. by 18 in.) + * 53 = A4 extra paper (236 mm by 322 mm) + * 54 = Letter transverse paper (8.275 in. by 11 in.) + * 55 = A4 transverse paper (210 mm by 297 mm) + * 56 = Letter extra transverse paper (9.275 in. by 12 in.) + * 57 = SuperA/SuperA/A4 paper (227 mm by 356 mm) + * 58 = SuperB/SuperB/A3 paper (305 mm by 487 mm) + * 59 = Letter plus paper (8.5 in. by 12.69 in.) + * 60 = A4 plus paper (210 mm by 330 mm) + * 61 = A5 transverse paper (148 mm by 210 mm) + * 62 = JIS B5 transverse paper (182 mm by 257 mm) + * 63 = A3 extra paper (322 mm by 445 mm) + * 64 = A5 extra paper (174 mm by 235 mm) + * 65 = ISO B5 extra paper (201 mm by 276 mm) + * 66 = A2 paper (420 mm by 594 mm) + * 67 = A3 transverse paper (297 mm by 420 mm) + * 68 = A3 extra transverse paper (322 mm by 445 mm) + * + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_PageSetup +{ + /* Paper size */ + const PAPERSIZE_LETTER = 1; + const PAPERSIZE_LETTER_SMALL = 2; + const PAPERSIZE_TABLOID = 3; + const PAPERSIZE_LEDGER = 4; + const PAPERSIZE_LEGAL = 5; + const PAPERSIZE_STATEMENT = 6; + const PAPERSIZE_EXECUTIVE = 7; + const PAPERSIZE_A3 = 8; + const PAPERSIZE_A4 = 9; + const PAPERSIZE_A4_SMALL = 10; + const PAPERSIZE_A5 = 11; + const PAPERSIZE_B4 = 12; + const PAPERSIZE_B5 = 13; + const PAPERSIZE_FOLIO = 14; + const PAPERSIZE_QUARTO = 15; + const PAPERSIZE_STANDARD_1 = 16; + const PAPERSIZE_STANDARD_2 = 17; + const PAPERSIZE_NOTE = 18; + const PAPERSIZE_NO9_ENVELOPE = 19; + const PAPERSIZE_NO10_ENVELOPE = 20; + const PAPERSIZE_NO11_ENVELOPE = 21; + const PAPERSIZE_NO12_ENVELOPE = 22; + const PAPERSIZE_NO14_ENVELOPE = 23; + const PAPERSIZE_C = 24; + const PAPERSIZE_D = 25; + const PAPERSIZE_E = 26; + const PAPERSIZE_DL_ENVELOPE = 27; + const PAPERSIZE_C5_ENVELOPE = 28; + const PAPERSIZE_C3_ENVELOPE = 29; + const PAPERSIZE_C4_ENVELOPE = 30; + const PAPERSIZE_C6_ENVELOPE = 31; + const PAPERSIZE_C65_ENVELOPE = 32; + const PAPERSIZE_B4_ENVELOPE = 33; + const PAPERSIZE_B5_ENVELOPE = 34; + const PAPERSIZE_B6_ENVELOPE = 35; + const PAPERSIZE_ITALY_ENVELOPE = 36; + const PAPERSIZE_MONARCH_ENVELOPE = 37; + const PAPERSIZE_6_3_4_ENVELOPE = 38; + const PAPERSIZE_US_STANDARD_FANFOLD = 39; + const PAPERSIZE_GERMAN_STANDARD_FANFOLD = 40; + const PAPERSIZE_GERMAN_LEGAL_FANFOLD = 41; + const PAPERSIZE_ISO_B4 = 42; + const PAPERSIZE_JAPANESE_DOUBLE_POSTCARD = 43; + const PAPERSIZE_STANDARD_PAPER_1 = 44; + const PAPERSIZE_STANDARD_PAPER_2 = 45; + const PAPERSIZE_STANDARD_PAPER_3 = 46; + const PAPERSIZE_INVITE_ENVELOPE = 47; + const PAPERSIZE_LETTER_EXTRA_PAPER = 48; + const PAPERSIZE_LEGAL_EXTRA_PAPER = 49; + const PAPERSIZE_TABLOID_EXTRA_PAPER = 50; + const PAPERSIZE_A4_EXTRA_PAPER = 51; + const PAPERSIZE_LETTER_TRANSVERSE_PAPER = 52; + const PAPERSIZE_A4_TRANSVERSE_PAPER = 53; + const PAPERSIZE_LETTER_EXTRA_TRANSVERSE_PAPER = 54; + const PAPERSIZE_SUPERA_SUPERA_A4_PAPER = 55; + const PAPERSIZE_SUPERB_SUPERB_A3_PAPER = 56; + const PAPERSIZE_LETTER_PLUS_PAPER = 57; + const PAPERSIZE_A4_PLUS_PAPER = 58; + const PAPERSIZE_A5_TRANSVERSE_PAPER = 59; + const PAPERSIZE_JIS_B5_TRANSVERSE_PAPER = 60; + const PAPERSIZE_A3_EXTRA_PAPER = 61; + const PAPERSIZE_A5_EXTRA_PAPER = 62; + const PAPERSIZE_ISO_B5_EXTRA_PAPER = 63; + const PAPERSIZE_A2_PAPER = 64; + const PAPERSIZE_A3_TRANSVERSE_PAPER = 65; + const PAPERSIZE_A3_EXTRA_TRANSVERSE_PAPER = 66; + + /* Page orientation */ + const ORIENTATION_DEFAULT = 'default'; + const ORIENTATION_LANDSCAPE = 'landscape'; + const ORIENTATION_PORTRAIT = 'portrait'; + + /* Print Range Set Method */ + const SETPRINTRANGE_OVERWRITE = 'O'; + const SETPRINTRANGE_INSERT = 'I'; + + + /** + * Paper size + * + * @var int + */ + private $_paperSize = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER; + + /** + * Orientation + * + * @var string + */ + private $_orientation = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT; + + /** + * Scale (Print Scale) + * + * Print scaling. Valid values range from 10 to 400 + * This setting is overridden when fitToWidth and/or fitToHeight are in use + * + * @var int? + */ + private $_scale = 100; + + /** + * Fit To Page + * Whether scale or fitToWith / fitToHeight applies + * + * @var boolean + */ + private $_fitToPage = FALSE; + + /** + * Fit To Height + * Number of vertical pages to fit on + * + * @var int? + */ + private $_fitToHeight = 1; + + /** + * Fit To Width + * Number of horizontal pages to fit on + * + * @var int? + */ + private $_fitToWidth = 1; + + /** + * Columns to repeat at left + * + * @var array Containing start column and end column, empty array if option unset + */ + private $_columnsToRepeatAtLeft = array('', ''); + + /** + * Rows to repeat at top + * + * @var array Containing start row number and end row number, empty array if option unset + */ + private $_rowsToRepeatAtTop = array(0, 0); + + /** + * Center page horizontally + * + * @var boolean + */ + private $_horizontalCentered = FALSE; + + /** + * Center page vertically + * + * @var boolean + */ + private $_verticalCentered = FALSE; + + /** + * Print area + * + * @var string + */ + private $_printArea = NULL; + + /** + * First page number + * + * @var int + */ + private $_firstPageNumber = NULL; + + /** + * Create a new PHPExcel_Worksheet_PageSetup + */ + public function __construct() + { + } + + /** + * Get Paper Size + * + * @return int + */ + public function getPaperSize() { + return $this->_paperSize; + } + + /** + * Set Paper Size + * + * @param int $pValue + * @return PHPExcel_Worksheet_PageSetup + */ + public function setPaperSize($pValue = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER) { + $this->_paperSize = $pValue; + return $this; + } + + /** + * Get Orientation + * + * @return string + */ + public function getOrientation() { + return $this->_orientation; + } + + /** + * Set Orientation + * + * @param string $pValue + * @return PHPExcel_Worksheet_PageSetup + */ + public function setOrientation($pValue = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) { + $this->_orientation = $pValue; + return $this; + } + + /** + * Get Scale + * + * @return int? + */ + public function getScale() { + return $this->_scale; + } + + /** + * Set Scale + * + * Print scaling. Valid values range from 10 to 400 + * This setting is overridden when fitToWidth and/or fitToHeight are in use + * + * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so scaling applies rather than fitToHeight / fitToWidth + * @return PHPExcel_Worksheet_PageSetup + * @throws PHPExcel_Exception + */ + public function setScale($pValue = 100, $pUpdate = true) { + // Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface, + // but it is apparently still able to handle any scale >= 0, where 0 results in 100 + if (($pValue >= 0) || is_null($pValue)) { + $this->_scale = $pValue; + if ($pUpdate) { + $this->_fitToPage = false; + } + } else { + throw new PHPExcel_Exception("Scale must not be negative"); + } + return $this; + } + + /** + * Get Fit To Page + * + * @return boolean + */ + public function getFitToPage() { + return $this->_fitToPage; + } + + /** + * Set Fit To Page + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_PageSetup + */ + public function setFitToPage($pValue = TRUE) { + $this->_fitToPage = $pValue; + return $this; + } + + /** + * Get Fit To Height + * + * @return int? + */ + public function getFitToHeight() { + return $this->_fitToHeight; + } + + /** + * Set Fit To Height + * + * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so it applies rather than scaling + * @return PHPExcel_Worksheet_PageSetup + */ + public function setFitToHeight($pValue = 1, $pUpdate = TRUE) { + $this->_fitToHeight = $pValue; + if ($pUpdate) { + $this->_fitToPage = TRUE; + } + return $this; + } + + /** + * Get Fit To Width + * + * @return int? + */ + public function getFitToWidth() { + return $this->_fitToWidth; + } + + /** + * Set Fit To Width + * + * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so it applies rather than scaling + * @return PHPExcel_Worksheet_PageSetup + */ + public function setFitToWidth($pValue = 1, $pUpdate = TRUE) { + $this->_fitToWidth = $pValue; + if ($pUpdate) { + $this->_fitToPage = TRUE; + } + return $this; + } + + /** + * Is Columns to repeat at left set? + * + * @return boolean + */ + public function isColumnsToRepeatAtLeftSet() { + if (is_array($this->_columnsToRepeatAtLeft)) { + if ($this->_columnsToRepeatAtLeft[0] != '' && $this->_columnsToRepeatAtLeft[1] != '') { + return true; + } + } + + return false; + } + + /** + * Get Columns to repeat at left + * + * @return array Containing start column and end column, empty array if option unset + */ + public function getColumnsToRepeatAtLeft() { + return $this->_columnsToRepeatAtLeft; + } + + /** + * Set Columns to repeat at left + * + * @param array $pValue Containing start column and end column, empty array if option unset + * @return PHPExcel_Worksheet_PageSetup + */ + public function setColumnsToRepeatAtLeft($pValue = null) { + if (is_array($pValue)) { + $this->_columnsToRepeatAtLeft = $pValue; + } + return $this; + } + + /** + * Set Columns to repeat at left by start and end + * + * @param string $pStart + * @param string $pEnd + * @return PHPExcel_Worksheet_PageSetup + */ + public function setColumnsToRepeatAtLeftByStartAndEnd($pStart = 'A', $pEnd = 'A') { + $this->_columnsToRepeatAtLeft = array($pStart, $pEnd); + return $this; + } + + /** + * Is Rows to repeat at top set? + * + * @return boolean + */ + public function isRowsToRepeatAtTopSet() { + if (is_array($this->_rowsToRepeatAtTop)) { + if ($this->_rowsToRepeatAtTop[0] != 0 && $this->_rowsToRepeatAtTop[1] != 0) { + return true; + } + } + + return false; + } + + /** + * Get Rows to repeat at top + * + * @return array Containing start column and end column, empty array if option unset + */ + public function getRowsToRepeatAtTop() { + return $this->_rowsToRepeatAtTop; + } + + /** + * Set Rows to repeat at top + * + * @param array $pValue Containing start column and end column, empty array if option unset + * @return PHPExcel_Worksheet_PageSetup + */ + public function setRowsToRepeatAtTop($pValue = null) { + if (is_array($pValue)) { + $this->_rowsToRepeatAtTop = $pValue; + } + return $this; + } + + /** + * Set Rows to repeat at top by start and end + * + * @param int $pStart + * @param int $pEnd + * @return PHPExcel_Worksheet_PageSetup + */ + public function setRowsToRepeatAtTopByStartAndEnd($pStart = 1, $pEnd = 1) { + $this->_rowsToRepeatAtTop = array($pStart, $pEnd); + return $this; + } + + /** + * Get center page horizontally + * + * @return bool + */ + public function getHorizontalCentered() { + return $this->_horizontalCentered; + } + + /** + * Set center page horizontally + * + * @param bool $value + * @return PHPExcel_Worksheet_PageSetup + */ + public function setHorizontalCentered($value = false) { + $this->_horizontalCentered = $value; + return $this; + } + + /** + * Get center page vertically + * + * @return bool + */ + public function getVerticalCentered() { + return $this->_verticalCentered; + } + + /** + * Set center page vertically + * + * @param bool $value + * @return PHPExcel_Worksheet_PageSetup + */ + public function setVerticalCentered($value = false) { + $this->_verticalCentered = $value; + return $this; + } + + /** + * Get print area + * + * @param int $index Identifier for a specific print area range if several ranges have been set + * Default behaviour, or a index value of 0, will return all ranges as a comma-separated string + * Otherwise, the specific range identified by the value of $index will be returned + * Print areas are numbered from 1 + * @throws PHPExcel_Exception + * @return string + */ + public function getPrintArea($index = 0) { + if ($index == 0) { + return $this->_printArea; + } + $printAreas = explode(',',$this->_printArea); + if (isset($printAreas[$index-1])) { + return $printAreas[$index-1]; + } + throw new PHPExcel_Exception("Requested Print Area does not exist"); + } + + /** + * Is print area set? + * + * @param int $index Identifier for a specific print area range if several ranges have been set + * Default behaviour, or an index value of 0, will identify whether any print range is set + * Otherwise, existence of the range identified by the value of $index will be returned + * Print areas are numbered from 1 + * @return boolean + */ + public function isPrintAreaSet($index = 0) { + if ($index == 0) { + return !is_null($this->_printArea); + } + $printAreas = explode(',',$this->_printArea); + return isset($printAreas[$index-1]); + } + + /** + * Clear a print area + * + * @param int $index Identifier for a specific print area range if several ranges have been set + * Default behaviour, or an index value of 0, will clear all print ranges that are set + * Otherwise, the range identified by the value of $index will be removed from the series + * Print areas are numbered from 1 + * @return PHPExcel_Worksheet_PageSetup + */ + public function clearPrintArea($index = 0) { + if ($index == 0) { + $this->_printArea = NULL; + } else { + $printAreas = explode(',',$this->_printArea); + if (isset($printAreas[$index-1])) { + unset($printAreas[$index-1]); + $this->_printArea = implode(',',$printAreas); + } + } + + return $this; + } + + /** + * Set print area. e.g. 'A1:D10' or 'A1:D10,G5:M20' + * + * @param string $value + * @param int $index Identifier for a specific print area range allowing several ranges to be set + * When the method is "O"verwrite, then a positive integer index will overwrite that indexed + * entry in the print areas list; a negative index value will identify which entry to + * overwrite working bacward through the print area to the list, with the last entry as -1. + * Specifying an index value of 0, will overwrite all existing print ranges. + * When the method is "I"nsert, then a positive index will insert after that indexed entry in + * the print areas list, while a negative index will insert before the indexed entry. + * Specifying an index value of 0, will always append the new print range at the end of the + * list. + * Print areas are numbered from 1 + * @param string $method Determines the method used when setting multiple print areas + * Default behaviour, or the "O" method, overwrites existing print area + * The "I" method, inserts the new print area before any specified index, or at the end of the list + * @return PHPExcel_Worksheet_PageSetup + * @throws PHPExcel_Exception + */ + public function setPrintArea($value, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE) { + if (strpos($value,'!') !== false) { + throw new PHPExcel_Exception('Cell coordinate must not specify a worksheet.'); + } elseif (strpos($value,':') === false) { + throw new PHPExcel_Exception('Cell coordinate must be a range of cells.'); + } elseif (strpos($value,'$') !== false) { + throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); + } + $value = strtoupper($value); + + if ($method == self::SETPRINTRANGE_OVERWRITE) { + if ($index == 0) { + $this->_printArea = $value; + } else { + $printAreas = explode(',',$this->_printArea); + if($index < 0) { + $index = count($printAreas) - abs($index) + 1; + } + if (($index <= 0) || ($index > count($printAreas))) { + throw new PHPExcel_Exception('Invalid index for setting print range.'); + } + $printAreas[$index-1] = $value; + $this->_printArea = implode(',',$printAreas); + } + } elseif($method == self::SETPRINTRANGE_INSERT) { + if ($index == 0) { + $this->_printArea .= ($this->_printArea == '') ? $value : ','.$value; + } else { + $printAreas = explode(',',$this->_printArea); + if($index < 0) { + $index = abs($index) - 1; + } + if ($index > count($printAreas)) { + throw new PHPExcel_Exception('Invalid index for setting print range.'); + } + $printAreas = array_merge(array_slice($printAreas,0,$index),array($value),array_slice($printAreas,$index)); + $this->_printArea = implode(',',$printAreas); + } + } else { + throw new PHPExcel_Exception('Invalid method for setting print range.'); + } + + return $this; + } + + /** + * Add a new print area (e.g. 'A1:D10' or 'A1:D10,G5:M20') to the list of print areas + * + * @param string $value + * @param int $index Identifier for a specific print area range allowing several ranges to be set + * A positive index will insert after that indexed entry in the print areas list, while a + * negative index will insert before the indexed entry. + * Specifying an index value of 0, will always append the new print range at the end of the + * list. + * Print areas are numbered from 1 + * @return PHPExcel_Worksheet_PageSetup + * @throws PHPExcel_Exception + */ + public function addPrintArea($value, $index = -1) { + return $this->setPrintArea($value, $index, self::SETPRINTRANGE_INSERT); + } + + /** + * Set print area + * + * @param int $column1 Column 1 + * @param int $row1 Row 1 + * @param int $column2 Column 2 + * @param int $row2 Row 2 + * @param int $index Identifier for a specific print area range allowing several ranges to be set + * When the method is "O"verwrite, then a positive integer index will overwrite that indexed + * entry in the print areas list; a negative index value will identify which entry to + * overwrite working bacward through the print area to the list, with the last entry as -1. + * Specifying an index value of 0, will overwrite all existing print ranges. + * When the method is "I"nsert, then a positive index will insert after that indexed entry in + * the print areas list, while a negative index will insert before the indexed entry. + * Specifying an index value of 0, will always append the new print range at the end of the + * list. + * Print areas are numbered from 1 + * @param string $method Determines the method used when setting multiple print areas + * Default behaviour, or the "O" method, overwrites existing print area + * The "I" method, inserts the new print area before any specified index, or at the end of the list + * @return PHPExcel_Worksheet_PageSetup + * @throws PHPExcel_Exception + */ + public function setPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE) + { + return $this->setPrintArea(PHPExcel_Cell::stringFromColumnIndex($column1) . $row1 . ':' . PHPExcel_Cell::stringFromColumnIndex($column2) . $row2, $index, $method); + } + + /** + * Add a new print area to the list of print areas + * + * @param int $column1 Start Column for the print area + * @param int $row1 Start Row for the print area + * @param int $column2 End Column for the print area + * @param int $row2 End Row for the print area + * @param int $index Identifier for a specific print area range allowing several ranges to be set + * A positive index will insert after that indexed entry in the print areas list, while a + * negative index will insert before the indexed entry. + * Specifying an index value of 0, will always append the new print range at the end of the + * list. + * Print areas are numbered from 1 + * @return PHPExcel_Worksheet_PageSetup + * @throws PHPExcel_Exception + */ + public function addPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = -1) + { + return $this->setPrintArea(PHPExcel_Cell::stringFromColumnIndex($column1) . $row1 . ':' . PHPExcel_Cell::stringFromColumnIndex($column2) . $row2, $index, self::SETPRINTRANGE_INSERT); + } + + /** + * Get first page number + * + * @return int + */ + public function getFirstPageNumber() { + return $this->_firstPageNumber; + } + + /** + * Set first page number + * + * @param int $value + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setFirstPageNumber($value = null) { + $this->_firstPageNumber = $value; + return $this; + } + + /** + * Reset first page number + * + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function resetFirstPageNumber() { + return $this->setFirstPageNumber(null); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/framework/library/phpexcel/PHPExcel/Worksheet/Protection.php b/framework/library/phpexcel/PHPExcel/Worksheet/Protection.php new file mode 100644 index 0000000..e9d6bb6 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Worksheet/Protection.php @@ -0,0 +1,545 @@ +_sheet || + $this->_objects || + $this->_scenarios || + $this->_formatCells || + $this->_formatColumns || + $this->_formatRows || + $this->_insertColumns || + $this->_insertRows || + $this->_insertHyperlinks || + $this->_deleteColumns || + $this->_deleteRows || + $this->_selectLockedCells || + $this->_sort || + $this->_autoFilter || + $this->_pivotTables || + $this->_selectUnlockedCells; + } + + /** + * Get Sheet + * + * @return boolean + */ + function getSheet() { + return $this->_sheet; + } + + /** + * Set Sheet + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setSheet($pValue = false) { + $this->_sheet = $pValue; + return $this; + } + + /** + * Get Objects + * + * @return boolean + */ + function getObjects() { + return $this->_objects; + } + + /** + * Set Objects + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setObjects($pValue = false) { + $this->_objects = $pValue; + return $this; + } + + /** + * Get Scenarios + * + * @return boolean + */ + function getScenarios() { + return $this->_scenarios; + } + + /** + * Set Scenarios + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setScenarios($pValue = false) { + $this->_scenarios = $pValue; + return $this; + } + + /** + * Get FormatCells + * + * @return boolean + */ + function getFormatCells() { + return $this->_formatCells; + } + + /** + * Set FormatCells + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setFormatCells($pValue = false) { + $this->_formatCells = $pValue; + return $this; + } + + /** + * Get FormatColumns + * + * @return boolean + */ + function getFormatColumns() { + return $this->_formatColumns; + } + + /** + * Set FormatColumns + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setFormatColumns($pValue = false) { + $this->_formatColumns = $pValue; + return $this; + } + + /** + * Get FormatRows + * + * @return boolean + */ + function getFormatRows() { + return $this->_formatRows; + } + + /** + * Set FormatRows + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setFormatRows($pValue = false) { + $this->_formatRows = $pValue; + return $this; + } + + /** + * Get InsertColumns + * + * @return boolean + */ + function getInsertColumns() { + return $this->_insertColumns; + } + + /** + * Set InsertColumns + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setInsertColumns($pValue = false) { + $this->_insertColumns = $pValue; + return $this; + } + + /** + * Get InsertRows + * + * @return boolean + */ + function getInsertRows() { + return $this->_insertRows; + } + + /** + * Set InsertRows + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setInsertRows($pValue = false) { + $this->_insertRows = $pValue; + return $this; + } + + /** + * Get InsertHyperlinks + * + * @return boolean + */ + function getInsertHyperlinks() { + return $this->_insertHyperlinks; + } + + /** + * Set InsertHyperlinks + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setInsertHyperlinks($pValue = false) { + $this->_insertHyperlinks = $pValue; + return $this; + } + + /** + * Get DeleteColumns + * + * @return boolean + */ + function getDeleteColumns() { + return $this->_deleteColumns; + } + + /** + * Set DeleteColumns + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setDeleteColumns($pValue = false) { + $this->_deleteColumns = $pValue; + return $this; + } + + /** + * Get DeleteRows + * + * @return boolean + */ + function getDeleteRows() { + return $this->_deleteRows; + } + + /** + * Set DeleteRows + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setDeleteRows($pValue = false) { + $this->_deleteRows = $pValue; + return $this; + } + + /** + * Get SelectLockedCells + * + * @return boolean + */ + function getSelectLockedCells() { + return $this->_selectLockedCells; + } + + /** + * Set SelectLockedCells + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setSelectLockedCells($pValue = false) { + $this->_selectLockedCells = $pValue; + return $this; + } + + /** + * Get Sort + * + * @return boolean + */ + function getSort() { + return $this->_sort; + } + + /** + * Set Sort + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setSort($pValue = false) { + $this->_sort = $pValue; + return $this; + } + + /** + * Get AutoFilter + * + * @return boolean + */ + function getAutoFilter() { + return $this->_autoFilter; + } + + /** + * Set AutoFilter + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setAutoFilter($pValue = false) { + $this->_autoFilter = $pValue; + return $this; + } + + /** + * Get PivotTables + * + * @return boolean + */ + function getPivotTables() { + return $this->_pivotTables; + } + + /** + * Set PivotTables + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setPivotTables($pValue = false) { + $this->_pivotTables = $pValue; + return $this; + } + + /** + * Get SelectUnlockedCells + * + * @return boolean + */ + function getSelectUnlockedCells() { + return $this->_selectUnlockedCells; + } + + /** + * Set SelectUnlockedCells + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setSelectUnlockedCells($pValue = false) { + $this->_selectUnlockedCells = $pValue; + return $this; + } + + /** + * Get Password (hashed) + * + * @return string + */ + function getPassword() { + return $this->_password; + } + + /** + * Set Password + * + * @param string $pValue + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @return PHPExcel_Worksheet_Protection + */ + function setPassword($pValue = '', $pAlreadyHashed = false) { + if (!$pAlreadyHashed) { + $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); + } + $this->_password = $pValue; + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php b/framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php new file mode 100644 index 0000000..443fefc --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php @@ -0,0 +1,1582 @@ +=,;#()"{} + const REGEX_SHEET_TITLE_UNQUOTED = '[^\*\:\/\\\\\?\[\]\+\-\% \\\'\^\&\<\>\=\,\;\#\(\)\"\{\}]+'; + + // Sheet title in quoted form (without surrounding quotes) + // Invalid sheet title characters cannot occur in the sheet title: + // *:/\?[] (usual invalid sheet title characters) + // Single quote is represented as a pair '' + const REGEX_SHEET_TITLE_QUOTED = '(([^\*\:\/\\\\\?\[\]\\\'])+|(\\\'\\\')+)+'; + + /** + * The index of the character we are currently looking at + * @var integer + */ + public $_current_char; + + /** + * The token we are working on. + * @var string + */ + public $_current_token; + + /** + * The formula to parse + * @var string + */ + public $_formula; + + /** + * The character ahead of the current char + * @var string + */ + public $_lookahead; + + /** + * The parse tree to be generated + * @var string + */ + public $_parse_tree; + + /** + * Array of external sheets + * @var array + */ + public $_ext_sheets; + + /** + * Array of sheet references in the form of REF structures + * @var array + */ + public $_references; + + /** + * The class constructor + * + */ + public function __construct() + { + $this->_current_char = 0; + $this->_current_token = ''; // The token we are working on. + $this->_formula = ''; // The formula to parse. + $this->_lookahead = ''; // The character ahead of the current char. + $this->_parse_tree = ''; // The parse tree to be generated. + $this->_initializeHashes(); // Initialize the hashes: ptg's and function's ptg's + $this->_ext_sheets = array(); + $this->_references = array(); + } + + /** + * Initialize the ptg and function hashes. + * + * @access private + */ + function _initializeHashes() + { + // The Excel ptg indices + $this->ptg = array( + 'ptgExp' => 0x01, + 'ptgTbl' => 0x02, + 'ptgAdd' => 0x03, + 'ptgSub' => 0x04, + 'ptgMul' => 0x05, + 'ptgDiv' => 0x06, + 'ptgPower' => 0x07, + 'ptgConcat' => 0x08, + 'ptgLT' => 0x09, + 'ptgLE' => 0x0A, + 'ptgEQ' => 0x0B, + 'ptgGE' => 0x0C, + 'ptgGT' => 0x0D, + 'ptgNE' => 0x0E, + 'ptgIsect' => 0x0F, + 'ptgUnion' => 0x10, + 'ptgRange' => 0x11, + 'ptgUplus' => 0x12, + 'ptgUminus' => 0x13, + 'ptgPercent' => 0x14, + 'ptgParen' => 0x15, + 'ptgMissArg' => 0x16, + 'ptgStr' => 0x17, + 'ptgAttr' => 0x19, + 'ptgSheet' => 0x1A, + 'ptgEndSheet' => 0x1B, + 'ptgErr' => 0x1C, + 'ptgBool' => 0x1D, + 'ptgInt' => 0x1E, + 'ptgNum' => 0x1F, + 'ptgArray' => 0x20, + 'ptgFunc' => 0x21, + 'ptgFuncVar' => 0x22, + 'ptgName' => 0x23, + 'ptgRef' => 0x24, + 'ptgArea' => 0x25, + 'ptgMemArea' => 0x26, + 'ptgMemErr' => 0x27, + 'ptgMemNoMem' => 0x28, + 'ptgMemFunc' => 0x29, + 'ptgRefErr' => 0x2A, + 'ptgAreaErr' => 0x2B, + 'ptgRefN' => 0x2C, + 'ptgAreaN' => 0x2D, + 'ptgMemAreaN' => 0x2E, + 'ptgMemNoMemN' => 0x2F, + 'ptgNameX' => 0x39, + 'ptgRef3d' => 0x3A, + 'ptgArea3d' => 0x3B, + 'ptgRefErr3d' => 0x3C, + 'ptgAreaErr3d' => 0x3D, + 'ptgArrayV' => 0x40, + 'ptgFuncV' => 0x41, + 'ptgFuncVarV' => 0x42, + 'ptgNameV' => 0x43, + 'ptgRefV' => 0x44, + 'ptgAreaV' => 0x45, + 'ptgMemAreaV' => 0x46, + 'ptgMemErrV' => 0x47, + 'ptgMemNoMemV' => 0x48, + 'ptgMemFuncV' => 0x49, + 'ptgRefErrV' => 0x4A, + 'ptgAreaErrV' => 0x4B, + 'ptgRefNV' => 0x4C, + 'ptgAreaNV' => 0x4D, + 'ptgMemAreaNV' => 0x4E, + 'ptgMemNoMemN' => 0x4F, + 'ptgFuncCEV' => 0x58, + 'ptgNameXV' => 0x59, + 'ptgRef3dV' => 0x5A, + 'ptgArea3dV' => 0x5B, + 'ptgRefErr3dV' => 0x5C, + 'ptgAreaErr3d' => 0x5D, + 'ptgArrayA' => 0x60, + 'ptgFuncA' => 0x61, + 'ptgFuncVarA' => 0x62, + 'ptgNameA' => 0x63, + 'ptgRefA' => 0x64, + 'ptgAreaA' => 0x65, + 'ptgMemAreaA' => 0x66, + 'ptgMemErrA' => 0x67, + 'ptgMemNoMemA' => 0x68, + 'ptgMemFuncA' => 0x69, + 'ptgRefErrA' => 0x6A, + 'ptgAreaErrA' => 0x6B, + 'ptgRefNA' => 0x6C, + 'ptgAreaNA' => 0x6D, + 'ptgMemAreaNA' => 0x6E, + 'ptgMemNoMemN' => 0x6F, + 'ptgFuncCEA' => 0x78, + 'ptgNameXA' => 0x79, + 'ptgRef3dA' => 0x7A, + 'ptgArea3dA' => 0x7B, + 'ptgRefErr3dA' => 0x7C, + 'ptgAreaErr3d' => 0x7D + ); + + // Thanks to Michael Meeks and Gnumeric for the initial arg values. + // + // The following hash was generated by "function_locale.pl" in the distro. + // Refer to function_locale.pl for non-English function names. + // + // The array elements are as follow: + // ptg: The Excel function ptg code. + // args: The number of arguments that the function takes: + // >=0 is a fixed number of arguments. + // -1 is a variable number of arguments. + // class: The reference, value or array class of the function args. + // vol: The function is volatile. + // + $this->_functions = array( + // function ptg args class vol + 'COUNT' => array( 0, -1, 0, 0 ), + 'IF' => array( 1, -1, 1, 0 ), + 'ISNA' => array( 2, 1, 1, 0 ), + 'ISERROR' => array( 3, 1, 1, 0 ), + 'SUM' => array( 4, -1, 0, 0 ), + 'AVERAGE' => array( 5, -1, 0, 0 ), + 'MIN' => array( 6, -1, 0, 0 ), + 'MAX' => array( 7, -1, 0, 0 ), + 'ROW' => array( 8, -1, 0, 0 ), + 'COLUMN' => array( 9, -1, 0, 0 ), + 'NA' => array( 10, 0, 0, 0 ), + 'NPV' => array( 11, -1, 1, 0 ), + 'STDEV' => array( 12, -1, 0, 0 ), + 'DOLLAR' => array( 13, -1, 1, 0 ), + 'FIXED' => array( 14, -1, 1, 0 ), + 'SIN' => array( 15, 1, 1, 0 ), + 'COS' => array( 16, 1, 1, 0 ), + 'TAN' => array( 17, 1, 1, 0 ), + 'ATAN' => array( 18, 1, 1, 0 ), + 'PI' => array( 19, 0, 1, 0 ), + 'SQRT' => array( 20, 1, 1, 0 ), + 'EXP' => array( 21, 1, 1, 0 ), + 'LN' => array( 22, 1, 1, 0 ), + 'LOG10' => array( 23, 1, 1, 0 ), + 'ABS' => array( 24, 1, 1, 0 ), + 'INT' => array( 25, 1, 1, 0 ), + 'SIGN' => array( 26, 1, 1, 0 ), + 'ROUND' => array( 27, 2, 1, 0 ), + 'LOOKUP' => array( 28, -1, 0, 0 ), + 'INDEX' => array( 29, -1, 0, 1 ), + 'REPT' => array( 30, 2, 1, 0 ), + 'MID' => array( 31, 3, 1, 0 ), + 'LEN' => array( 32, 1, 1, 0 ), + 'VALUE' => array( 33, 1, 1, 0 ), + 'TRUE' => array( 34, 0, 1, 0 ), + 'FALSE' => array( 35, 0, 1, 0 ), + 'AND' => array( 36, -1, 0, 0 ), + 'OR' => array( 37, -1, 0, 0 ), + 'NOT' => array( 38, 1, 1, 0 ), + 'MOD' => array( 39, 2, 1, 0 ), + 'DCOUNT' => array( 40, 3, 0, 0 ), + 'DSUM' => array( 41, 3, 0, 0 ), + 'DAVERAGE' => array( 42, 3, 0, 0 ), + 'DMIN' => array( 43, 3, 0, 0 ), + 'DMAX' => array( 44, 3, 0, 0 ), + 'DSTDEV' => array( 45, 3, 0, 0 ), + 'VAR' => array( 46, -1, 0, 0 ), + 'DVAR' => array( 47, 3, 0, 0 ), + 'TEXT' => array( 48, 2, 1, 0 ), + 'LINEST' => array( 49, -1, 0, 0 ), + 'TREND' => array( 50, -1, 0, 0 ), + 'LOGEST' => array( 51, -1, 0, 0 ), + 'GROWTH' => array( 52, -1, 0, 0 ), + 'PV' => array( 56, -1, 1, 0 ), + 'FV' => array( 57, -1, 1, 0 ), + 'NPER' => array( 58, -1, 1, 0 ), + 'PMT' => array( 59, -1, 1, 0 ), + 'RATE' => array( 60, -1, 1, 0 ), + 'MIRR' => array( 61, 3, 0, 0 ), + 'IRR' => array( 62, -1, 0, 0 ), + 'RAND' => array( 63, 0, 1, 1 ), + 'MATCH' => array( 64, -1, 0, 0 ), + 'DATE' => array( 65, 3, 1, 0 ), + 'TIME' => array( 66, 3, 1, 0 ), + 'DAY' => array( 67, 1, 1, 0 ), + 'MONTH' => array( 68, 1, 1, 0 ), + 'YEAR' => array( 69, 1, 1, 0 ), + 'WEEKDAY' => array( 70, -1, 1, 0 ), + 'HOUR' => array( 71, 1, 1, 0 ), + 'MINUTE' => array( 72, 1, 1, 0 ), + 'SECOND' => array( 73, 1, 1, 0 ), + 'NOW' => array( 74, 0, 1, 1 ), + 'AREAS' => array( 75, 1, 0, 1 ), + 'ROWS' => array( 76, 1, 0, 1 ), + 'COLUMNS' => array( 77, 1, 0, 1 ), + 'OFFSET' => array( 78, -1, 0, 1 ), + 'SEARCH' => array( 82, -1, 1, 0 ), + 'TRANSPOSE' => array( 83, 1, 1, 0 ), + 'TYPE' => array( 86, 1, 1, 0 ), + 'ATAN2' => array( 97, 2, 1, 0 ), + 'ASIN' => array( 98, 1, 1, 0 ), + 'ACOS' => array( 99, 1, 1, 0 ), + 'CHOOSE' => array( 100, -1, 1, 0 ), + 'HLOOKUP' => array( 101, -1, 0, 0 ), + 'VLOOKUP' => array( 102, -1, 0, 0 ), + 'ISREF' => array( 105, 1, 0, 0 ), + 'LOG' => array( 109, -1, 1, 0 ), + 'CHAR' => array( 111, 1, 1, 0 ), + 'LOWER' => array( 112, 1, 1, 0 ), + 'UPPER' => array( 113, 1, 1, 0 ), + 'PROPER' => array( 114, 1, 1, 0 ), + 'LEFT' => array( 115, -1, 1, 0 ), + 'RIGHT' => array( 116, -1, 1, 0 ), + 'EXACT' => array( 117, 2, 1, 0 ), + 'TRIM' => array( 118, 1, 1, 0 ), + 'REPLACE' => array( 119, 4, 1, 0 ), + 'SUBSTITUTE' => array( 120, -1, 1, 0 ), + 'CODE' => array( 121, 1, 1, 0 ), + 'FIND' => array( 124, -1, 1, 0 ), + 'CELL' => array( 125, -1, 0, 1 ), + 'ISERR' => array( 126, 1, 1, 0 ), + 'ISTEXT' => array( 127, 1, 1, 0 ), + 'ISNUMBER' => array( 128, 1, 1, 0 ), + 'ISBLANK' => array( 129, 1, 1, 0 ), + 'T' => array( 130, 1, 0, 0 ), + 'N' => array( 131, 1, 0, 0 ), + 'DATEVALUE' => array( 140, 1, 1, 0 ), + 'TIMEVALUE' => array( 141, 1, 1, 0 ), + 'SLN' => array( 142, 3, 1, 0 ), + 'SYD' => array( 143, 4, 1, 0 ), + 'DDB' => array( 144, -1, 1, 0 ), + 'INDIRECT' => array( 148, -1, 1, 1 ), + 'CALL' => array( 150, -1, 1, 0 ), + 'CLEAN' => array( 162, 1, 1, 0 ), + 'MDETERM' => array( 163, 1, 2, 0 ), + 'MINVERSE' => array( 164, 1, 2, 0 ), + 'MMULT' => array( 165, 2, 2, 0 ), + 'IPMT' => array( 167, -1, 1, 0 ), + 'PPMT' => array( 168, -1, 1, 0 ), + 'COUNTA' => array( 169, -1, 0, 0 ), + 'PRODUCT' => array( 183, -1, 0, 0 ), + 'FACT' => array( 184, 1, 1, 0 ), + 'DPRODUCT' => array( 189, 3, 0, 0 ), + 'ISNONTEXT' => array( 190, 1, 1, 0 ), + 'STDEVP' => array( 193, -1, 0, 0 ), + 'VARP' => array( 194, -1, 0, 0 ), + 'DSTDEVP' => array( 195, 3, 0, 0 ), + 'DVARP' => array( 196, 3, 0, 0 ), + 'TRUNC' => array( 197, -1, 1, 0 ), + 'ISLOGICAL' => array( 198, 1, 1, 0 ), + 'DCOUNTA' => array( 199, 3, 0, 0 ), + 'USDOLLAR' => array( 204, -1, 1, 0 ), + 'FINDB' => array( 205, -1, 1, 0 ), + 'SEARCHB' => array( 206, -1, 1, 0 ), + 'REPLACEB' => array( 207, 4, 1, 0 ), + 'LEFTB' => array( 208, -1, 1, 0 ), + 'RIGHTB' => array( 209, -1, 1, 0 ), + 'MIDB' => array( 210, 3, 1, 0 ), + 'LENB' => array( 211, 1, 1, 0 ), + 'ROUNDUP' => array( 212, 2, 1, 0 ), + 'ROUNDDOWN' => array( 213, 2, 1, 0 ), + 'ASC' => array( 214, 1, 1, 0 ), + 'DBCS' => array( 215, 1, 1, 0 ), + 'RANK' => array( 216, -1, 0, 0 ), + 'ADDRESS' => array( 219, -1, 1, 0 ), + 'DAYS360' => array( 220, -1, 1, 0 ), + 'TODAY' => array( 221, 0, 1, 1 ), + 'VDB' => array( 222, -1, 1, 0 ), + 'MEDIAN' => array( 227, -1, 0, 0 ), + 'SUMPRODUCT' => array( 228, -1, 2, 0 ), + 'SINH' => array( 229, 1, 1, 0 ), + 'COSH' => array( 230, 1, 1, 0 ), + 'TANH' => array( 231, 1, 1, 0 ), + 'ASINH' => array( 232, 1, 1, 0 ), + 'ACOSH' => array( 233, 1, 1, 0 ), + 'ATANH' => array( 234, 1, 1, 0 ), + 'DGET' => array( 235, 3, 0, 0 ), + 'INFO' => array( 244, 1, 1, 1 ), + 'DB' => array( 247, -1, 1, 0 ), + 'FREQUENCY' => array( 252, 2, 0, 0 ), + 'ERROR.TYPE' => array( 261, 1, 1, 0 ), + 'REGISTER.ID' => array( 267, -1, 1, 0 ), + 'AVEDEV' => array( 269, -1, 0, 0 ), + 'BETADIST' => array( 270, -1, 1, 0 ), + 'GAMMALN' => array( 271, 1, 1, 0 ), + 'BETAINV' => array( 272, -1, 1, 0 ), + 'BINOMDIST' => array( 273, 4, 1, 0 ), + 'CHIDIST' => array( 274, 2, 1, 0 ), + 'CHIINV' => array( 275, 2, 1, 0 ), + 'COMBIN' => array( 276, 2, 1, 0 ), + 'CONFIDENCE' => array( 277, 3, 1, 0 ), + 'CRITBINOM' => array( 278, 3, 1, 0 ), + 'EVEN' => array( 279, 1, 1, 0 ), + 'EXPONDIST' => array( 280, 3, 1, 0 ), + 'FDIST' => array( 281, 3, 1, 0 ), + 'FINV' => array( 282, 3, 1, 0 ), + 'FISHER' => array( 283, 1, 1, 0 ), + 'FISHERINV' => array( 284, 1, 1, 0 ), + 'FLOOR' => array( 285, 2, 1, 0 ), + 'GAMMADIST' => array( 286, 4, 1, 0 ), + 'GAMMAINV' => array( 287, 3, 1, 0 ), + 'CEILING' => array( 288, 2, 1, 0 ), + 'HYPGEOMDIST' => array( 289, 4, 1, 0 ), + 'LOGNORMDIST' => array( 290, 3, 1, 0 ), + 'LOGINV' => array( 291, 3, 1, 0 ), + 'NEGBINOMDIST' => array( 292, 3, 1, 0 ), + 'NORMDIST' => array( 293, 4, 1, 0 ), + 'NORMSDIST' => array( 294, 1, 1, 0 ), + 'NORMINV' => array( 295, 3, 1, 0 ), + 'NORMSINV' => array( 296, 1, 1, 0 ), + 'STANDARDIZE' => array( 297, 3, 1, 0 ), + 'ODD' => array( 298, 1, 1, 0 ), + 'PERMUT' => array( 299, 2, 1, 0 ), + 'POISSON' => array( 300, 3, 1, 0 ), + 'TDIST' => array( 301, 3, 1, 0 ), + 'WEIBULL' => array( 302, 4, 1, 0 ), + 'SUMXMY2' => array( 303, 2, 2, 0 ), + 'SUMX2MY2' => array( 304, 2, 2, 0 ), + 'SUMX2PY2' => array( 305, 2, 2, 0 ), + 'CHITEST' => array( 306, 2, 2, 0 ), + 'CORREL' => array( 307, 2, 2, 0 ), + 'COVAR' => array( 308, 2, 2, 0 ), + 'FORECAST' => array( 309, 3, 2, 0 ), + 'FTEST' => array( 310, 2, 2, 0 ), + 'INTERCEPT' => array( 311, 2, 2, 0 ), + 'PEARSON' => array( 312, 2, 2, 0 ), + 'RSQ' => array( 313, 2, 2, 0 ), + 'STEYX' => array( 314, 2, 2, 0 ), + 'SLOPE' => array( 315, 2, 2, 0 ), + 'TTEST' => array( 316, 4, 2, 0 ), + 'PROB' => array( 317, -1, 2, 0 ), + 'DEVSQ' => array( 318, -1, 0, 0 ), + 'GEOMEAN' => array( 319, -1, 0, 0 ), + 'HARMEAN' => array( 320, -1, 0, 0 ), + 'SUMSQ' => array( 321, -1, 0, 0 ), + 'KURT' => array( 322, -1, 0, 0 ), + 'SKEW' => array( 323, -1, 0, 0 ), + 'ZTEST' => array( 324, -1, 0, 0 ), + 'LARGE' => array( 325, 2, 0, 0 ), + 'SMALL' => array( 326, 2, 0, 0 ), + 'QUARTILE' => array( 327, 2, 0, 0 ), + 'PERCENTILE' => array( 328, 2, 0, 0 ), + 'PERCENTRANK' => array( 329, -1, 0, 0 ), + 'MODE' => array( 330, -1, 2, 0 ), + 'TRIMMEAN' => array( 331, 2, 0, 0 ), + 'TINV' => array( 332, 2, 1, 0 ), + 'CONCATENATE' => array( 336, -1, 1, 0 ), + 'POWER' => array( 337, 2, 1, 0 ), + 'RADIANS' => array( 342, 1, 1, 0 ), + 'DEGREES' => array( 343, 1, 1, 0 ), + 'SUBTOTAL' => array( 344, -1, 0, 0 ), + 'SUMIF' => array( 345, -1, 0, 0 ), + 'COUNTIF' => array( 346, 2, 0, 0 ), + 'COUNTBLANK' => array( 347, 1, 0, 0 ), + 'ISPMT' => array( 350, 4, 1, 0 ), + 'DATEDIF' => array( 351, 3, 1, 0 ), + 'DATESTRING' => array( 352, 1, 1, 0 ), + 'NUMBERSTRING' => array( 353, 2, 1, 0 ), + 'ROMAN' => array( 354, -1, 1, 0 ), + 'GETPIVOTDATA' => array( 358, -1, 0, 0 ), + 'HYPERLINK' => array( 359, -1, 1, 0 ), + 'PHONETIC' => array( 360, 1, 0, 0 ), + 'AVERAGEA' => array( 361, -1, 0, 0 ), + 'MAXA' => array( 362, -1, 0, 0 ), + 'MINA' => array( 363, -1, 0, 0 ), + 'STDEVPA' => array( 364, -1, 0, 0 ), + 'VARPA' => array( 365, -1, 0, 0 ), + 'STDEVA' => array( 366, -1, 0, 0 ), + 'VARA' => array( 367, -1, 0, 0 ), + 'BAHTTEXT' => array( 368, 1, 0, 0 ), + ); + } + + /** + * Convert a token to the proper ptg value. + * + * @access private + * @param mixed $token The token to convert. + * @return mixed the converted token on success + */ + function _convert($token) + { + if (preg_match("/\"([^\"]|\"\"){0,255}\"/", $token)) { + return $this->_convertString($token); + + } elseif (is_numeric($token)) { + return $this->_convertNumber($token); + + // match references like A1 or $A$1 + } elseif (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$token)) { + return $this->_convertRef2d($token); + + // match external references like Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1 + } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { + return $this->_convertRef3d($token); + + // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1 + } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { + return $this->_convertRef3d($token); + + // match ranges like A1:B2 or $A$1:$B$2 + } elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\:(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/', $token)) { + return $this->_convertRange2d($token); + + // match external ranges like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 + } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { + return $this->_convertRange3d($token); + + // match external ranges like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 + } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { + return $this->_convertRange3d($token); + + // operators (including parentheses) + } elseif (isset($this->ptg[$token])) { + return pack("C", $this->ptg[$token]); + + // match error codes + } elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $token) or $token == '#N/A') { + return $this->_convertError($token); + + // commented so argument number can be processed correctly. See toReversePolish(). + /*elseif (preg_match("/[A-Z0-9\xc0-\xdc\.]+/",$token)) + { + return($this->_convertFunction($token,$this->_func_args)); + }*/ + + // if it's an argument, ignore the token (the argument remains) + } elseif ($token == 'arg') { + return ''; + } + + // TODO: use real error codes + throw new PHPExcel_Writer_Exception("Unknown token $token"); + } + + /** + * Convert a number token to ptgInt or ptgNum + * + * @access private + * @param mixed $num an integer or double for conversion to its ptg value + */ + function _convertNumber($num) + { + // Integer in the range 0..2**16-1 + if ((preg_match("/^\d+$/", $num)) and ($num <= 65535)) { + return pack("Cv", $this->ptg['ptgInt'], $num); + } else { // A float + if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) { // if it's Big Endian + $num = strrev($num); + } + return pack("Cd", $this->ptg['ptgNum'], $num); + } + } + + /** + * Convert a string token to ptgStr + * + * @access private + * @param string $string A string for conversion to its ptg value. + * @return mixed the converted token on success + */ + function _convertString($string) + { + // chop away beggining and ending quotes + $string = substr($string, 1, strlen($string) - 2); + if (strlen($string) > 255) { + throw new PHPExcel_Writer_Exception("String is too long"); + } + + return pack('C', $this->ptg['ptgStr']) . PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($string); + } + + /** + * Convert a function to a ptgFunc or ptgFuncVarV depending on the number of + * args that it takes. + * + * @access private + * @param string $token The name of the function for convertion to ptg value. + * @param integer $num_args The number of arguments the function receives. + * @return string The packed ptg for the function + */ + function _convertFunction($token, $num_args) + { + $args = $this->_functions[$token][1]; +// $volatile = $this->_functions[$token][3]; + + // Fixed number of args eg. TIME($i,$j,$k). + if ($args >= 0) { + return pack("Cv", $this->ptg['ptgFuncV'], $this->_functions[$token][0]); + } + // Variable number of args eg. SUM($i,$j,$k, ..). + if ($args == -1) { + return pack("CCv", $this->ptg['ptgFuncVarV'], $num_args, $this->_functions[$token][0]); + } + } + + /** + * Convert an Excel range such as A1:D4 to a ptgRefV. + * + * @access private + * @param string $range An Excel range in the A1:A2 + * @param int $class + */ + function _convertRange2d($range, $class=0) + { + + // TODO: possible class value 0,1,2 check Formula.pm + // Split the range into 2 cell refs + if (preg_match('/^(\$)?([A-Ia-i]?[A-Za-z])(\$)?(\d+)\:(\$)?([A-Ia-i]?[A-Za-z])(\$)?(\d+)$/', $range)) { + list($cell1, $cell2) = explode(':', $range); + } else { + // TODO: use real error codes + throw new PHPExcel_Writer_Exception("Unknown range separator"); + } + + // Convert the cell references + list($row1, $col1) = $this->_cellToPackedRowcol($cell1); + list($row2, $col2) = $this->_cellToPackedRowcol($cell2); + + // The ptg value depends on the class of the ptg. + if ($class == 0) { + $ptgArea = pack("C", $this->ptg['ptgArea']); + } elseif ($class == 1) { + $ptgArea = pack("C", $this->ptg['ptgAreaV']); + } elseif ($class == 2) { + $ptgArea = pack("C", $this->ptg['ptgAreaA']); + } else { + // TODO: use real error codes + throw new PHPExcel_Writer_Exception("Unknown class $class"); + } + return $ptgArea . $row1 . $row2 . $col1. $col2; + } + + /** + * Convert an Excel 3d range such as "Sheet1!A1:D4" or "Sheet1:Sheet2!A1:D4" to + * a ptgArea3d. + * + * @access private + * @param string $token An Excel range in the Sheet1!A1:A2 format. + * @return mixed The packed ptgArea3d token on success. + */ + function _convertRange3d($token) + { +// $class = 0; // formulas like Sheet1!$A$1:$A$2 in list type data validation need this class (0x3B) + + // Split the ref at the ! symbol + list($ext_ref, $range) = explode('!', $token); + + // Convert the external reference part (different for BIFF8) + $ext_ref = $this->_getRefIndex($ext_ref); + + // Split the range into 2 cell refs + list($cell1, $cell2) = explode(':', $range); + + // Convert the cell references + if (preg_match("/^(\\$)?[A-Ia-i]?[A-Za-z](\\$)?(\d+)$/", $cell1)) { + list($row1, $col1) = $this->_cellToPackedRowcol($cell1); + list($row2, $col2) = $this->_cellToPackedRowcol($cell2); + } else { // It's a rows range (like 26:27) + list($row1, $col1, $row2, $col2) = $this->_rangeToPackedRange($cell1.':'.$cell2); + } + + // The ptg value depends on the class of the ptg. +// if ($class == 0) { + $ptgArea = pack("C", $this->ptg['ptgArea3d']); +// } elseif ($class == 1) { +// $ptgArea = pack("C", $this->ptg['ptgArea3dV']); +// } elseif ($class == 2) { +// $ptgArea = pack("C", $this->ptg['ptgArea3dA']); +// } else { +// throw new PHPExcel_Writer_Exception("Unknown class $class"); +// } + + return $ptgArea . $ext_ref . $row1 . $row2 . $col1. $col2; + } + + /** + * Convert an Excel reference such as A1, $B2, C$3 or $D$4 to a ptgRefV. + * + * @access private + * @param string $cell An Excel cell reference + * @return string The cell in packed() format with the corresponding ptg + */ + function _convertRef2d($cell) + { +// $class = 2; // as far as I know, this is magick. + + // Convert the cell reference + $cell_array = $this->_cellToPackedRowcol($cell); + list($row, $col) = $cell_array; + + // The ptg value depends on the class of the ptg. +// if ($class == 0) { +// $ptgRef = pack("C", $this->ptg['ptgRef']); +// } elseif ($class == 1) { +// $ptgRef = pack("C", $this->ptg['ptgRefV']); +// } elseif ($class == 2) { + $ptgRef = pack("C", $this->ptg['ptgRefA']); +// } else { +// // TODO: use real error codes +// throw new PHPExcel_Writer_Exception("Unknown class $class"); +// } + return $ptgRef.$row.$col; + } + + /** + * Convert an Excel 3d reference such as "Sheet1!A1" or "Sheet1:Sheet2!A1" to a + * ptgRef3d. + * + * @access private + * @param string $cell An Excel cell reference + * @return mixed The packed ptgRef3d token on success. + */ + function _convertRef3d($cell) + { +// $class = 2; // as far as I know, this is magick. + + // Split the ref at the ! symbol + list($ext_ref, $cell) = explode('!', $cell); + + // Convert the external reference part (different for BIFF8) + $ext_ref = $this->_getRefIndex($ext_ref); + + // Convert the cell reference part + list($row, $col) = $this->_cellToPackedRowcol($cell); + + // The ptg value depends on the class of the ptg. +// if ($class == 0) { +// $ptgRef = pack("C", $this->ptg['ptgRef3d']); +// } elseif ($class == 1) { +// $ptgRef = pack("C", $this->ptg['ptgRef3dV']); +// } elseif ($class == 2) { + $ptgRef = pack("C", $this->ptg['ptgRef3dA']); +// } else { +// throw new PHPExcel_Writer_Exception("Unknown class $class"); +// } + + return $ptgRef . $ext_ref. $row . $col; + } + + /** + * Convert an error code to a ptgErr + * + * @access private + * @param string $errorCode The error code for conversion to its ptg value + * @return string The error code ptgErr + */ + function _convertError($errorCode) + { + switch ($errorCode) { + case '#NULL!': return pack("C", 0x00); + case '#DIV/0!': return pack("C", 0x07); + case '#VALUE!': return pack("C", 0x0F); + case '#REF!': return pack("C", 0x17); + case '#NAME?': return pack("C", 0x1D); + case '#NUM!': return pack("C", 0x24); + case '#N/A': return pack("C", 0x2A); + } + return pack("C", 0xFF); + } + + /** + * Convert the sheet name part of an external reference, for example "Sheet1" or + * "Sheet1:Sheet2", to a packed structure. + * + * @access private + * @param string $ext_ref The name of the external reference + * @return string The reference index in packed() format + */ + function _packExtRef($ext_ref) + { + $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any. + $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any. + + // Check if there is a sheet range eg., Sheet1:Sheet2. + if (preg_match("/:/", $ext_ref)) { + list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); + + $sheet1 = $this->_getSheetIndex($sheet_name1); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula"); + } + $sheet2 = $this->_getSheetIndex($sheet_name2); + if ($sheet2 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula"); + } + + // Reverse max and min sheet numbers if necessary + if ($sheet1 > $sheet2) { + list($sheet1, $sheet2) = array($sheet2, $sheet1); + } + } else { // Single sheet name only. + $sheet1 = $this->_getSheetIndex($ext_ref); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula"); + } + $sheet2 = $sheet1; + } + + // References are stored relative to 0xFFFF. + $offset = -1 - $sheet1; + + return pack('vdvv', $offset, 0x00, $sheet1, $sheet2); + } + + /** + * Look up the REF index that corresponds to an external sheet name + * (or range). If it doesn't exist yet add it to the workbook's references + * array. It assumes all sheet names given must exist. + * + * @access private + * @param string $ext_ref The name of the external reference + * @return mixed The reference index in packed() format on success + */ + function _getRefIndex($ext_ref) + { + $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any. + $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any. + $ext_ref = str_replace('\'\'', '\'', $ext_ref); // Replace escaped '' with ' + + // Check if there is a sheet range eg., Sheet1:Sheet2. + if (preg_match("/:/", $ext_ref)) { + list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); + + $sheet1 = $this->_getSheetIndex($sheet_name1); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula"); + } + $sheet2 = $this->_getSheetIndex($sheet_name2); + if ($sheet2 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula"); + } + + // Reverse max and min sheet numbers if necessary + if ($sheet1 > $sheet2) { + list($sheet1, $sheet2) = array($sheet2, $sheet1); + } + } else { // Single sheet name only. + $sheet1 = $this->_getSheetIndex($ext_ref); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula"); + } + $sheet2 = $sheet1; + } + + // assume all references belong to this document + $supbook_index = 0x00; + $ref = pack('vvv', $supbook_index, $sheet1, $sheet2); + $total_references = count($this->_references); + $index = -1; + for ($i = 0; $i < $total_references; ++$i) { + if ($ref == $this->_references[$i]) { + $index = $i; + break; + } + } + // if REF was not found add it to references array + if ($index == -1) { + $this->_references[$total_references] = $ref; + $index = $total_references; + } + + return pack('v', $index); + } + + /** + * Look up the index that corresponds to an external sheet name. The hash of + * sheet names is updated by the addworksheet() method of the + * PHPExcel_Writer_Excel5_Workbook class. + * + * @access private + * @param string $sheet_name Sheet name + * @return integer The sheet index, -1 if the sheet was not found + */ + function _getSheetIndex($sheet_name) + { + if (!isset($this->_ext_sheets[$sheet_name])) { + return -1; + } else { + return $this->_ext_sheets[$sheet_name]; + } + } + + /** + * This method is used to update the array of sheet names. It is + * called by the addWorksheet() method of the + * PHPExcel_Writer_Excel5_Workbook class. + * + * @access public + * @see PHPExcel_Writer_Excel5_Workbook::addWorksheet() + * @param string $name The name of the worksheet being added + * @param integer $index The index of the worksheet being added + */ + function setExtSheet($name, $index) + { + $this->_ext_sheets[$name] = $index; + } + + /** + * pack() row and column into the required 3 or 4 byte format. + * + * @access private + * @param string $cell The Excel cell reference to be packed + * @return array Array containing the row and column in packed() format + */ + function _cellToPackedRowcol($cell) + { + $cell = strtoupper($cell); + list($row, $col, $row_rel, $col_rel) = $this->_cellToRowcol($cell); + if ($col >= 256) { + throw new PHPExcel_Writer_Exception("Column in: $cell greater than 255"); + } + if ($row >= 65536) { + throw new PHPExcel_Writer_Exception("Row in: $cell greater than 65536 "); + } + + // Set the high bits to indicate if row or col are relative. + $col |= $col_rel << 14; + $col |= $row_rel << 15; + $col = pack('v', $col); + + $row = pack('v', $row); + + return array($row, $col); + } + + /** + * pack() row range into the required 3 or 4 byte format. + * Just using maximum col/rows, which is probably not the correct solution + * + * @access private + * @param string $range The Excel range to be packed + * @return array Array containing (row1,col1,row2,col2) in packed() format + */ + function _rangeToPackedRange($range) + { + preg_match('/(\$)?(\d+)\:(\$)?(\d+)/', $range, $match); + // return absolute rows if there is a $ in the ref + $row1_rel = empty($match[1]) ? 1 : 0; + $row1 = $match[2]; + $row2_rel = empty($match[3]) ? 1 : 0; + $row2 = $match[4]; + // Convert 1-index to zero-index + --$row1; + --$row2; + // Trick poor inocent Excel + $col1 = 0; + $col2 = 65535; // FIXME: maximum possible value for Excel 5 (change this!!!) + + // FIXME: this changes for BIFF8 + if (($row1 >= 65536) or ($row2 >= 65536)) { + throw new PHPExcel_Writer_Exception("Row in: $range greater than 65536 "); + } + + // Set the high bits to indicate if rows are relative. + $col1 |= $row1_rel << 15; + $col2 |= $row2_rel << 15; + $col1 = pack('v', $col1); + $col2 = pack('v', $col2); + + $row1 = pack('v', $row1); + $row2 = pack('v', $row2); + + return array($row1, $col1, $row2, $col2); + } + + /** + * Convert an Excel cell reference such as A1 or $B2 or C$3 or $D$4 to a zero + * indexed row and column number. Also returns two (0,1) values to indicate + * whether the row or column are relative references. + * + * @access private + * @param string $cell The Excel cell reference in A1 format. + * @return array + */ + function _cellToRowcol($cell) + { + preg_match('/(\$)?([A-I]?[A-Z])(\$)?(\d+)/',$cell,$match); + // return absolute column if there is a $ in the ref + $col_rel = empty($match[1]) ? 1 : 0; + $col_ref = $match[2]; + $row_rel = empty($match[3]) ? 1 : 0; + $row = $match[4]; + + // Convert base26 column string to a number. + $expn = strlen($col_ref) - 1; + $col = 0; + $col_ref_length = strlen($col_ref); + for ($i = 0; $i < $col_ref_length; ++$i) { + $col += (ord($col_ref{$i}) - 64) * pow(26, $expn); + --$expn; + } + + // Convert 1-index to zero-index + --$row; + --$col; + + return array($row, $col, $row_rel, $col_rel); + } + + /** + * Advance to the next valid token. + * + * @access private + */ + function _advance() + { + $i = $this->_current_char; + $formula_length = strlen($this->_formula); + // eat up white spaces + if ($i < $formula_length) { + while ($this->_formula{$i} == " ") { + ++$i; + } + + if ($i < ($formula_length - 1)) { + $this->_lookahead = $this->_formula{$i+1}; + } + $token = ''; + } + + while ($i < $formula_length) { + $token .= $this->_formula{$i}; + + if ($i < ($formula_length - 1)) { + $this->_lookahead = $this->_formula{$i+1}; + } else { + $this->_lookahead = ''; + } + + if ($this->_match($token) != '') { + //if ($i < strlen($this->_formula) - 1) { + // $this->_lookahead = $this->_formula{$i+1}; + //} + $this->_current_char = $i + 1; + $this->_current_token = $token; + return 1; + } + + if ($i < ($formula_length - 2)) { + $this->_lookahead = $this->_formula{$i+2}; + } else { // if we run out of characters _lookahead becomes empty + $this->_lookahead = ''; + } + ++$i; + } + //die("Lexical error ".$this->_current_char); + } + + /** + * Checks if it's a valid token. + * + * @access private + * @param mixed $token The token to check. + * @return mixed The checked token or false on failure + */ + function _match($token) + { + switch($token) { + case "+": + case "-": + case "*": + case "/": + case "(": + case ")": + case ",": + case ";": + case ">=": + case "<=": + case "=": + case "<>": + case "^": + case "&": + case "%": + return $token; + break; + case ">": + if ($this->_lookahead == '=') { // it's a GE token + break; + } + return $token; + break; + case "<": + // it's a LE or a NE token + if (($this->_lookahead == '=') or ($this->_lookahead == '>')) { + break; + } + return $token; + break; + default: + // if it's a reference A1 or $A$1 or $A1 or A$1 + if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and + !preg_match("/[0-9]/",$this->_lookahead) and + ($this->_lookahead != ':') and ($this->_lookahead != '.') and + ($this->_lookahead != '!')) + { + return $token; + } + // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead) and + ($this->_lookahead != ':') and ($this->_lookahead != '.')) + { + return $token; + } + // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead) and + ($this->_lookahead != ':') and ($this->_lookahead != '.')) + { + return $token; + } + // if it's a range A1:A2 or $A$1:$A$2 + elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/', $token) and + !preg_match("/[0-9]/",$this->_lookahead)) + { + return $token; + } + // If it's an external range like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead)) + { + return $token; + } + // If it's an external range like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead)) + { + return $token; + } + // If it's a number (check that it's not a sheet name or range) + elseif (is_numeric($token) and + (!is_numeric($token.$this->_lookahead) or ($this->_lookahead == '')) and + ($this->_lookahead != '!') and ($this->_lookahead != ':')) + { + return $token; + } + // If it's a string (of maximum 255 characters) + elseif (preg_match("/\"([^\"]|\"\"){0,255}\"/",$token) and $this->_lookahead != '"' and (substr_count($token, '"')%2 == 0)) + { + return $token; + } + // If it's an error code + elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $token) or $token == '#N/A') + { + return $token; + } + // if it's a function call + elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$token) and ($this->_lookahead == "(")) + { + return $token; + } + // It's an argument of some description (e.g. a named range), + // precise nature yet to be determined + elseif(substr($token,-1) == ')') { + return $token; + } + return ''; + } + } + + /** + * The parsing method. It parses a formula. + * + * @access public + * @param string $formula The formula to parse, without the initial equal + * sign (=). + * @return mixed true on success + */ + function parse($formula) + { + $this->_current_char = 0; + $this->_formula = $formula; + $this->_lookahead = isset($formula{1}) ? $formula{1} : ''; + $this->_advance(); + $this->_parse_tree = $this->_condition(); + return true; + } + + /** + * It parses a condition. It assumes the following rule: + * Cond -> Expr [(">" | "<") Expr] + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _condition() + { + $result = $this->_expression(); + if ($this->_current_token == "<") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgLT', $result, $result2); + } elseif ($this->_current_token == ">") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgGT', $result, $result2); + } elseif ($this->_current_token == "<=") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgLE', $result, $result2); + } elseif ($this->_current_token == ">=") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgGE', $result, $result2); + } elseif ($this->_current_token == "=") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgEQ', $result, $result2); + } elseif ($this->_current_token == "<>") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgNE', $result, $result2); + } elseif ($this->_current_token == "&") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgConcat', $result, $result2); + } + return $result; + } + + /** + * It parses a expression. It assumes the following rule: + * Expr -> Term [("+" | "-") Term] + * -> "string" + * -> "-" Term : Negative value + * -> "+" Term : Positive value + * -> Error code + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _expression() + { + // If it's a string return a string node + if (preg_match("/\"([^\"]|\"\"){0,255}\"/", $this->_current_token)) { + $tmp = str_replace('""', '"', $this->_current_token); + if (($tmp == '"') || ($tmp == '')) $tmp = '""'; // Trap for "" that has been used for an empty string + $result = $this->_createTree($tmp, '', ''); + $this->_advance(); + return $result; + // If it's an error code + } elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $this->_current_token) or $this->_current_token == '#N/A'){ + $result = $this->_createTree($this->_current_token, 'ptgErr', ''); + $this->_advance(); + return $result; + // If it's a negative value + } elseif ($this->_current_token == "-") { + // catch "-" Term + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgUminus', $result2, ''); + return $result; + // If it's a positive value + } elseif ($this->_current_token == "+") { + // catch "+" Term + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgUplus', $result2, ''); + return $result; + } + $result = $this->_term(); + while (($this->_current_token == "+") or + ($this->_current_token == "-") or + ($this->_current_token == "^")) { + /**/ + if ($this->_current_token == "+") { + $this->_advance(); + $result2 = $this->_term(); + $result = $this->_createTree('ptgAdd', $result, $result2); + } elseif ($this->_current_token == "-") { + $this->_advance(); + $result2 = $this->_term(); + $result = $this->_createTree('ptgSub', $result, $result2); + } else { + $this->_advance(); + $result2 = $this->_term(); + $result = $this->_createTree('ptgPower', $result, $result2); + } + } + return $result; + } + + /** + * This function just introduces a ptgParen element in the tree, so that Excel + * doesn't get confused when working with a parenthesized formula afterwards. + * + * @access private + * @see _fact() + * @return array The parsed ptg'd tree + */ + function _parenthesizedExpression() + { + $result = $this->_createTree('ptgParen', $this->_expression(), ''); + return $result; + } + + /** + * It parses a term. It assumes the following rule: + * Term -> Fact [("*" | "/") Fact] + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _term() + { + $result = $this->_fact(); + while (($this->_current_token == "*") or + ($this->_current_token == "/")) { + /**/ + if ($this->_current_token == "*") { + $this->_advance(); + $result2 = $this->_fact(); + $result = $this->_createTree('ptgMul', $result, $result2); + } else { + $this->_advance(); + $result2 = $this->_fact(); + $result = $this->_createTree('ptgDiv', $result, $result2); + } + } + return $result; + } + + /** + * It parses a factor. It assumes the following rule: + * Fact -> ( Expr ) + * | CellRef + * | CellRange + * | Number + * | Function + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _fact() + { + if ($this->_current_token == "(") { + $this->_advance(); // eat the "(" + $result = $this->_parenthesizedExpression(); + if ($this->_current_token != ")") { + throw new PHPExcel_Writer_Exception("')' token expected."); + } + $this->_advance(); // eat the ")" + return $result; + } + // if it's a reference + if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$this->_current_token)) + { + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) + { + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) + { + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // if it's a range A1:B2 or $A$1:$B$2 + elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token) or + preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token)) + { + // must be an error? + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external range (Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) + { + // must be an error? + //$result = $this->_current_token; + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external range ('Sheet1'!A1:B2 or 'Sheet1'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1'!$A$1:$B$2) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) + { + // must be an error? + //$result = $this->_current_token; + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's a number or a percent + elseif (is_numeric($this->_current_token)) + { + if($this->_lookahead == '%'){ + $result = $this->_createTree('ptgPercent', $this->_current_token, ''); + } else { + $result = $this->_createTree($this->_current_token, '', ''); + } + $this->_advance(); + return $result; + } + // if it's a function call + elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$this->_current_token)) + { + $result = $this->_func(); + return $result; + } + throw new PHPExcel_Writer_Exception("Syntax error: ".$this->_current_token. + ", lookahead: ".$this->_lookahead. + ", current char: ".$this->_current_char); + } + + /** + * It parses a function call. It assumes the following rule: + * Func -> ( Expr [,Expr]* ) + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _func() + { + $num_args = 0; // number of arguments received + $function = strtoupper($this->_current_token); + $result = ''; // initialize result + $this->_advance(); + $this->_advance(); // eat the "(" + while ($this->_current_token != ')') { + /**/ + if ($num_args > 0) { + if ($this->_current_token == "," or + $this->_current_token == ";") + { + $this->_advance(); // eat the "," or ";" + } else { + throw new PHPExcel_Writer_Exception("Syntax error: comma expected in ". + "function $function, arg #{$num_args}"); + } + $result2 = $this->_condition(); + $result = $this->_createTree('arg', $result, $result2); + } else { // first argument + $result2 = $this->_condition(); + $result = $this->_createTree('arg', '', $result2); + } + ++$num_args; + } + if (!isset($this->_functions[$function])) { + throw new PHPExcel_Writer_Exception("Function $function() doesn't exist"); + } + $args = $this->_functions[$function][1]; + // If fixed number of args eg. TIME($i,$j,$k). Check that the number of args is valid. + if (($args >= 0) and ($args != $num_args)) { + throw new PHPExcel_Writer_Exception("Incorrect number of arguments in function $function() "); + } + + $result = $this->_createTree($function, $result, $num_args); + $this->_advance(); // eat the ")" + return $result; + } + + /** + * Creates a tree. In fact an array which may have one or two arrays (sub-trees) + * as elements. + * + * @access private + * @param mixed $value The value of this node. + * @param mixed $left The left array (sub-tree) or a final node. + * @param mixed $right The right array (sub-tree) or a final node. + * @return array A tree + */ + function _createTree($value, $left, $right) + { + return array('value' => $value, 'left' => $left, 'right' => $right); + } + + /** + * Builds a string containing the tree in reverse polish notation (What you + * would use in a HP calculator stack). + * The following tree: + * + * + + * / \ + * 2 3 + * + * produces: "23+" + * + * The following tree: + * + * + + * / \ + * 3 * + * / \ + * 6 A1 + * + * produces: "36A1*+" + * + * In fact all operands, functions, references, etc... are written as ptg's + * + * @access public + * @param array $tree The optional tree to convert. + * @return string The tree in reverse polish notation + */ + function toReversePolish($tree = array()) + { + $polish = ""; // the string we are going to return + if (empty($tree)) { // If it's the first call use _parse_tree + $tree = $this->_parse_tree; + } + + if (is_array($tree['left'])) { + $converted_tree = $this->toReversePolish($tree['left']); + $polish .= $converted_tree; + } elseif ($tree['left'] != '') { // It's a final node + $converted_tree = $this->_convert($tree['left']); + $polish .= $converted_tree; + } + if (is_array($tree['right'])) { + $converted_tree = $this->toReversePolish($tree['right']); + $polish .= $converted_tree; + } elseif ($tree['right'] != '') { // It's a final node + $converted_tree = $this->_convert($tree['right']); + $polish .= $converted_tree; + } + // if it's a function convert it here (so we can set it's arguments) + if (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/",$tree['value']) and + !preg_match('/^([A-Ia-i]?[A-Za-z])(\d+)$/',$tree['value']) and + !preg_match("/^[A-Ia-i]?[A-Za-z](\d+)\.\.[A-Ia-i]?[A-Za-z](\d+)$/",$tree['value']) and + !is_numeric($tree['value']) and + !isset($this->ptg[$tree['value']])) + { + // left subtree for a function is always an array. + if ($tree['left'] != '') { + $left_tree = $this->toReversePolish($tree['left']); + } else { + $left_tree = ''; + } + // add it's left subtree and return. + return $left_tree.$this->_convertFunction($tree['value'], $tree['right']); + } else { + $converted_tree = $this->_convert($tree['value']); + } + $polish .= $converted_tree; + return $polish; + } + +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php b/framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php new file mode 100644 index 0000000..912ba9d --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php @@ -0,0 +1,190 @@ +setPHPExcel($pPHPExcel); + + $writerPartsArray = array( + 'content' => 'PHPExcel_Writer_OpenDocument_Content', + 'meta' => 'PHPExcel_Writer_OpenDocument_Meta', + 'meta_inf' => 'PHPExcel_Writer_OpenDocument_MetaInf', + 'mimetype' => 'PHPExcel_Writer_OpenDocument_Mimetype', + 'settings' => 'PHPExcel_Writer_OpenDocument_Settings', + 'styles' => 'PHPExcel_Writer_OpenDocument_Styles', + 'thumbnails' => 'PHPExcel_Writer_OpenDocument_Thumbnails' + ); + + foreach ($writerPartsArray as $writer => $class) { + $this->writerParts[$writer] = new $class($this); + } + } + + /** + * Get writer part + * + * @param string $pPartName Writer part name + * @return PHPExcel_Writer_Excel2007_WriterPart + */ + public function getWriterPart($pPartName = '') + { + if ($pPartName != '' && isset($this->writerParts[strtolower($pPartName)])) { + return $this->writerParts[strtolower($pPartName)]; + } else { + return null; + } + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) + { + if (!$this->spreadSheet) { + throw new PHPExcel_Writer_Exception('PHPExcel object unassigned.'); + } + + // garbage collect + $this->spreadSheet->garbageCollect(); + + // If $pFilename is php://output or php://stdout, make it a temporary file... + $originalFilename = $pFilename; + if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') { + $pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp'); + if ($pFilename == '') { + $pFilename = $originalFilename; + } + } + + $objZip = $this->createZip($pFilename); + + $objZip->addFromString('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest()); + $objZip->addFromString('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail()); + $objZip->addFromString('content.xml', $this->getWriterPart('content')->write()); + $objZip->addFromString('meta.xml', $this->getWriterPart('meta')->write()); + $objZip->addFromString('mimetype', $this->getWriterPart('mimetype')->write()); + $objZip->addFromString('settings.xml', $this->getWriterPart('settings')->write()); + $objZip->addFromString('styles.xml', $this->getWriterPart('styles')->write()); + + // Close file + if ($objZip->close() === false) { + throw new PHPExcel_Writer_Exception("Could not close zip file $pFilename."); + } + + // If a temporary file was used, copy it to the correct file stream + if ($originalFilename != $pFilename) { + if (copy($pFilename, $originalFilename) === false) { + throw new PHPExcel_Writer_Exception("Could not copy temporary zip file $pFilename to $originalFilename."); + } + @unlink($pFilename); + } + } + + /** + * Create zip object + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + * @return ZipArchive + */ + private function createZip($pFilename) + { + // Create new ZIP file and open it for writing + $zipClass = PHPExcel_Settings::getZipClass(); + $objZip = new $zipClass(); + + // Retrieve OVERWRITE and CREATE constants from the instantiated zip class + // This method of accessing constant values from a dynamic class should work with all appropriate versions of PHP + $ro = new ReflectionObject($objZip); + $zipOverWrite = $ro->getConstant('OVERWRITE'); + $zipCreate = $ro->getConstant('CREATE'); + + if (file_exists($pFilename)) { + unlink($pFilename); + } + // Try opening the ZIP file + if ($objZip->open($pFilename, $zipOverWrite) !== true) { + if ($objZip->open($pFilename, $zipCreate) !== true) { + throw new PHPExcel_Writer_Exception("Could not open $pFilename for writing."); + } + } + + return $objZip; + } + + /** + * Get PHPExcel object + * + * @return PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function getPHPExcel() + { + if ($this->spreadSheet !== null) { + return $this->spreadSheet; + } else { + throw new PHPExcel_Writer_Exception('No PHPExcel assigned.'); + } + } + + /** + * Set PHPExcel object + * + * @param PHPExcel $pPHPExcel PHPExcel object + * @throws PHPExcel_Writer_Exception + * @return PHPExcel_Writer_Excel2007 + */ + public function setPHPExcel(PHPExcel $pPHPExcel = null) + { + $this->spreadSheet = $pPHPExcel; + return $this; + } +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/PDF.php b/framework/library/phpexcel/PHPExcel/Writer/PDF.php new file mode 100644 index 0000000..ed31195 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/PDF.php @@ -0,0 +1,90 @@ +_renderer = new $rendererName($phpExcel); + } + + + /** + * Magic method to handle direct calls to the configured PDF renderer wrapper class. + * + * @param string $name Renderer library method name + * @param mixed[] $arguments Array of arguments to pass to the renderer method + * @return mixed Returned data from the PDF renderer wrapper method + */ + public function __call($name, $arguments) + { + if ($this->_renderer === NULL) { + throw new PHPExcel_Writer_Exception("PDF Rendering library has not been defined."); + } + + return call_user_func_array(array($this->_renderer, $name), $arguments); + } + +} diff --git a/web/common/permission.inc.php b/web/common/permission.inc.php new file mode 100644 index 0000000..7c77b29 --- /dev/null +++ b/web/common/permission.inc.php @@ -0,0 +1,943 @@ + + array ( + 'default' => '', + 'direct' => + array ( + 0 => 'auth', + 1 => 'welcome', + ), + 'vice_founder' => + array ( + 0 => 'account*', + ), + 'owner' => + array ( + 0 => 'account*', + ), + 'manager' => + array ( + 0 => 'common-info', + 1 => 'display', + 2 => 'manage', + 3 => 'post-step', + 4 => 'post-user', + 5 => 'post', + 6 => 'create', + ), + 'operator' => + array ( + 0 => 'common-info', + 1 => 'display', + 2 => 'manage', + 3 => 'post-step', + 4 => 'create', + ), + 'clerk' => + array ( + 0 => 'display', + ), + 'unbind_user' => + array ( + ), + ), + 'advertisement' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + ), + 'owner' => + array ( + ), + 'manager' => + array ( + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'article' => + array ( + 'default' => '', + 'direct' => + array ( + 0 => 'notice-show', + 1 => 'news-show', + ), + 'vice_founder' => + array ( + ), + 'owner' => + array ( + ), + 'manager' => + array ( + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'message' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'notice', + ), + 'owner' => + array ( + 0 => 'notice', + ), + 'manager' => + array ( + 0 => 'notice', + ), + 'operator' => + array ( + 0 => 'notice', + ), + 'clerk' => + array ( + 0 => 'notice', + ), + 'unbind_user' => + array ( + 0 => 'notice', + ), + ), + 'cloud' => + array ( + 'default' => 'touch', + 'direct' => + array ( + 0 => 'touch', + 1 => 'dock', + ), + 'vice_founder' => + array ( + ), + 'owner' => + array ( + ), + 'manager' => + array ( + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'cron' => + array ( + 'default' => '', + 'direct' => + array ( + 0 => 'entry', + ), + 'vice_founder' => + array ( + ), + 'owner' => + array ( + ), + 'manager' => + array ( + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'founder' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + ), + 'owner' => + array ( + ), + 'manager' => + array ( + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'help' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'help*', + ), + 'owner' => + array ( + 0 => 'help*', + ), + 'manager' => + array ( + 0 => 'help*', + ), + 'operator' => + array ( + 0 => 'help*', + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'home' => + array ( + 'default' => 'welcome', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'home*', + ), + 'owner' => + array ( + 0 => 'home*', + ), + 'manager' => + array ( + 0 => 'home*', + ), + 'operator' => + array ( + 0 => 'home*', + ), + 'clerk' => + array ( + 0 => 'welcome', + ), + 'unbind_user' => + array ( + ), + 'expired' => + array ( + 0 => 'welcome', + ), + ), + 'mc' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'mc*', + ), + 'owner' => + array ( + 0 => 'mc*', + ), + 'manager' => + array ( + 0 => 'chats', + 1 => 'fields', + 2 => 'group', + 3 => 'trade', + 4 => 'fans', + 5 => 'member', + 6 => 'message', + ), + 'operator' => + array ( + 0 => 'chats', + 1 => 'fields', + 2 => 'group', + 3 => 'trade', + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'module' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'module*', + ), + 'owner' => + array ( + 0 => 'manage-account', + 1 => 'manage-system', + 2 => 'permission', + 3 => 'display', + 4 => 'welcome', + 5 => 'link', + 6 => 'link-account', + 7 => 'shortcut', + 8 => 'plugin', + ), + 'manager' => + array ( + 0 => 'manage-account', + 1 => 'display', + 2 => 'welcome', + 3 => 'link', + 4 => 'link-account', + 5 => 'shortcut', + 6 => 'plugin', + ), + 'operator' => + array ( + 0 => 'manage-account', + 1 => 'display', + 2 => 'welcome', + 3 => 'link', + 4 => 'link-account', + 5 => 'shortcut', + 6 => 'plugin', + ), + 'clerk' => + array ( + 0 => 'display', + 1 => 'manage-account', + 2 => 'welcome', + 3 => 'link', + 4 => 'link-account', + 5 => 'shortcut', + 6 => 'plugin', + ), + 'unbind_user' => + array ( + ), + ), + 'platform' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'platform*', + ), + 'owner' => + array ( + 0 => 'platform*', + ), + 'manager' => + array ( + 0 => 'cover', + 1 => 'reply', + 2 => 'menu', + 3 => 'qr', + 4 => 'mass', + 5 => 'material', + 6 => 'material-post', + 7 => 'url2qr', + ), + 'operator' => + array ( + 0 => 'cover', + 1 => 'reply', + 2 => 'material', + 3 => 'material-post', + 4 => 'url2qr', + ), + 'clerk' => + array ( + 0 => 'reply', + 1 => 'cover', + 2 => 'material', + 3 => 'material-post', + ), + 'unbind_user' => + array ( + ), + ), + 'profile' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'profile*', + ), + 'owner' => + array ( + 0 => 'profile*', + ), + 'manager' => + array ( + 0 => 'remote', + 1 => 'passport', + 2 => 'tplnotice', + 3 => 'notify', + 4 => 'common', + 5 => 'payment', + 6 => 'refund', + 7 => 'module-link-uniacid', + 8 => 'bind-domain', + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + 0 => 'profile*', + ), + ), + 'site' => + array ( + 'default' => '', + 'direct' => + array ( + 0 => 'entry', + ), + 'vice_founder' => + array ( + 0 => 'site*', + ), + 'owner' => + array ( + 0 => 'site*', + ), + 'manager' => + array ( + 0 => 'editor', + 1 => 'article', + 2 => 'category', + 3 => 'style', + 4 => 'nav', + 5 => 'slide', + 6 => 'multi', + 7 => 'comment', + ), + 'operator' => + array ( + 0 => 'editor', + 1 => 'article', + 2 => 'category', + 3 => 'style', + 4 => 'nav', + 5 => 'slide', + ), + 'clerk' => + array ( + 0 => 'nav', + ), + 'unbind_user' => + array ( + ), + ), + 'statistics' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'statistics*', + ), + 'owner' => + array ( + 0 => 'statistics*', + ), + 'manager' => + array ( + 0 => 'app', + 1 => 'site', + 2 => 'setting', + 3 => 'fans', + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'store' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'goods-buyer', + 1 => 'orders', + ), + 'owner' => + array ( + 0 => 'goods-buyer', + 1 => 'orders', + ), + 'manager' => + array ( + 0 => 'goods-buyer', + 1 => 'orders', + ), + 'operator' => + array ( + 0 => 'goods-buyer', + 1 => 'orders', + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + 'expired' => + array ( + 0 => 'goods-buyer', + 1 => 'orders', + ), + ), + 'system' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'updatecache', + ), + 'owner' => + array ( + 0 => 'updatecache', + ), + 'manager' => + array ( + 0 => 'updatecache', + ), + 'operator' => + array ( + 0 => 'updatecache', + ), + 'clerk' => + array ( + 0 => 'updatecache', + ), + 'unbind_user' => + array ( + 0 => 'updatecache', + ), + 'expired' => + array ( + 0 => 'updatecache', + ), + ), + 'user' => + array ( + 'default' => 'display', + 'direct' => + array ( + 0 => 'login', + 1 => 'register', + 2 => 'logout', + 3 => 'find-password', + 4 => 'third-bind', + 5 => 'agreement-show', + ), + 'vice_founder' => + array ( + 0 => 'user*', + ), + 'owner' => + array ( + 0 => 'profile', + ), + 'manager' => + array ( + 0 => 'profile', + ), + 'operator' => + array ( + 0 => 'profile', + ), + 'clerk' => + array ( + 0 => 'profile', + ), + 'unbind_user' => + array ( + 0 => 'profile', + ), + 'expired' => + array ( + 0 => 'user*', + ), + ), + 'miniapp' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'miniapp*', + ), + 'owner' => + array ( + 0 => 'miniapp*', + ), + 'manager' => + array ( + 0 => 'display', + 1 => 'version', + 2 => 'post', + ), + 'operator' => + array ( + 0 => 'display', + 1 => 'version', + 2 => 'post', + ), + 'clerk' => + array ( + 0 => 'display', + 1 => 'version', + 2 => 'post', + ), + 'unbind_user' => + array ( + ), + ), + 'wxapp' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'wxapp*', + ), + 'owner' => + array ( + 0 => 'wxapp*', + ), + 'manager' => + array ( + 0 => 'display', + 1 => 'version', + 2 => 'post', + 3 => 'auth', + 4 => 'manage', + ), + 'operator' => + array ( + 0 => 'display', + 1 => 'version', + 2 => 'post', + 3 => 'auth', + ), + 'clerk' => + array ( + 0 => 'display', + ), + 'unbind_user' => + array ( + ), + ), + 'webapp' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'webapp*', + ), + 'owner' => + array ( + 0 => 'webapp*', + ), + 'manager' => + array ( + 0 => 'home', + 1 => 'manage', + ), + 'operator' => + array ( + 0 => 'home', + 1 => 'manage', + ), + 'clerk' => + array ( + 0 => 'home', + ), + 'unbind_user' => + array ( + ), + ), + 'phoneapp' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'phoneapp*', + ), + 'owner' => + array ( + 0 => 'phoneapp*', + ), + 'manager' => + array ( + 0 => 'display', + 1 => 'manage', + 2 => 'version', + ), + 'operator' => + array ( + 0 => 'display', + 1 => 'manage', + 2 => 'version', + ), + 'clerk' => + array ( + 0 => 'display', + ), + ), + 'utility' => + array ( + 'default' => '', + 'direct' => + array ( + 0 => 'verifycode', + 1 => 'code', + 2 => 'bindcall', + 3 => 'subscribe', + 4 => 'wxcode', + 5 => 'modules', + 6 => 'link', + 7 => 'visit', + 8 => 'file', + ), + 'vice_founder' => + array ( + 0 => 'user', + 1 => 'emulator', + 2 => 'file', + ), + 'owner' => + array ( + 0 => 'emulator', + 1 => 'file', + ), + 'manager' => + array ( + 0 => 'emulator', + 1 => 'file', + ), + 'operator' => + array ( + 0 => 'emulator', + 1 => 'file', + ), + 'clerk' => + array ( + 0 => 'emulator', + 1 => 'file', + ), + 'unbind_user' => + array ( + ), + ), + 'append' => + array ( + 0 => 'append*', + ), + 'see_more_info' => + array ( + 'founder' => + array ( + 0 => 'see_module_manage_system_except_installed', + 1 => 'see_module_manage_system_ugrade', + 2 => 'see_module_manage_system_stop', + 3 => 'see_module_manage_system_install', + 4 => 'see_module_manage_system_shopinfo', + 5 => 'see_module_manage_system_info_edit', + 6 => 'see_module_manage_system_detailinfo', + 7 => 'see_module_manage_system_group_add', + 8 => 'see_module_manage_system_welcome_support', + 9 => 'see_account_post_modules_tpl_edit_store_endtime', + 10 => 'see_account_manage_module_tpl_all_permission', + 11 => 'see_account_manage_sms_blance', + 12 => 'see_account_manage_users_edit_vicefounder', + 13 => 'see_account_manage_users_edit_owner', + 14 => 'see_account_manage_users_set_permission_for_manager', + 15 => 'see_account_manage_users_set_permission_for_operator', + 16 => 'see_account_manage_users_addmanager', + 17 => 'see_account_manage_users_delmanager', + 18 => 'see_account_manage_users_deloperator', + 19 => 'see_account_manage_users_adduser', + 20 => 'see_account_manage_users_add_viceuser', + 21 => 'see_account_manage_display', + 22 => 'see_account_manage_recycle', + 23 => 'see_account_manage_system_platform', + 24 => 'see_account_manage_expired_message', + 25 => 'see_permission_create_account_group', + 26 => 'see_permission_module_group', + 27 => 'see_permission_user_group', + 28 => 'see_permission_founder_group', + 29 => 'see_system_upgrade', + 30 => 'see_system_manage_clerk', + 31 => 'see_system_manage_vice_founder', + 32 => 'see_system_add_vice_founder', + 33 => 'see_notice_post', + 34 => 'see_message_official', + 35 => 'see_message_order', + 36 => 'see_message_register', + 37 => 'see_message_worker', + 38 => 'see_module_manage_system_newversion', + 39 => 'see_user_add_welcome_account', + 40 => 'see_user_edit_base_founder_name', + 41 => 'see_user_create_own_vice_founder', + 42 => 'see_user_profile_account_num', + 43 => 'see_user_profile_edit_username', + 44 => 'see_user_manage_display', + 45 => 'see_user_manage_founder', + 46 => 'see_user_manage_clerk', + 47 => 'see_user_manage_check', + 48 => 'see_user_manage_recycle', + 49 => 'see_user_manage_fields', + 50 => 'see_user_manage_expire', + 51 => 'see_workorder', + 52 => 'see_controller', + 53 => 'see_modules_deactivate', + ), + 'vice_founder' => + array ( + 0 => 'see_account_manage_users_adduser', + 1 => 'see_account_manage_users_edit_owner', + 2 => 'see_account_manage_users_set_permission_for_manager', + 3 => 'see_account_manage_users_set_permission_for_operator', + 4 => 'see_account_manage_users_deloperator', + 5 => 'see_account_manage_users_delmanager', + 6 => 'see_account_manage_display', + 7 => 'see_account_manage_recycle', + 8 => 'see_module_manage_system_group_add', + 9 => 'see_permission_create_account_group', + 10 => 'see_permission_module_group', + 11 => 'see_permission_user_group', + 12 => 'see_user_add_welcome_account', + 13 => 'see_user_profile_account_num', + 14 => 'see_user_manage_display', + 15 => 'see_user_manage_check', + 16 => 'see_user_manage_recycle', + 17 => 'see_controller', + ), + 'owner' => + array ( + 0 => 'see_account_manage_users_set_permission_for_manager', + 1 => 'see_account_manage_users_set_permission_for_operator', + 2 => 'see_account_manage_users_deloperator', + 3 => 'see_account_manage_users_delmanager', + 4 => 'see_account_manage_display', + 5 => 'see_account_manage_recycle', + 6 => 'see_modules_recharge', + 7 => 'see_user_add_welcome_account', + 8 => 'see_user_profile_account_num', + ), + 'manager' => + array ( + 0 => 'see_account_manage_users_set_permission_for_operator', + 1 => 'see_account_manage_users_deloperator', + 2 => 'see_account_manage_display', + 3 => 'see_user_profile_welcome', + 4 => 'see_user_add_welcome_account', + 5 => 'see_user_profile_account_num', + ), + 'operator' => + array ( + 0 => 'see_account_manage_display', + 1 => 'see_user_profile_welcome', + 2 => 'see_user_add_welcome_account', + 3 => 'see_user_profile_account_num', + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + 0 => 'see_user_profile_welcome', + ), + 'expired' => + array ( + ), + ), +); +return $we7_file_permission; \ No newline at end of file diff --git a/web/resource/components/kindeditor/plugins/code/prettify.css b/web/resource/components/kindeditor/plugins/code/prettify.css new file mode 100644 index 0000000..b8287e5 --- /dev/null +++ b/web/resource/components/kindeditor/plugins/code/prettify.css @@ -0,0 +1,13 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} + +pre.prettyprint { + border: 0; + border-left: 3px solid rgb(204, 204, 204); + margin-left: 2em; + padding: 0.5em; + font-size: 110%; + display: block; + font-family: "Consolas", "Monaco", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace; + margin: 1em 0px; + white-space: pre; +} diff --git a/web/resource/components/kindeditor/plugins/code/prettify.js b/web/resource/components/kindeditor/plugins/code/prettify.js new file mode 100644 index 0000000..eef5ad7 --- /dev/null +++ b/web/resource/components/kindeditor/plugins/code/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + + +(function(K) { + +function KSWFUpload(options) { + this.init(options); +} +K.extend(KSWFUpload, { + init : function(options) { + var self = this; + options.afterError = options.afterError || function(str) { + alert(str); + }; + self.options = options; + self.progressbars = {}; + // template + self.div = K(options.container).html([ + '
', + '
', + '
', + '', + '
', + '
' + options.uploadDesc + '
', + '', + '', + '', + '
', + '
', + '
' + ].join('')); + self.bodyDiv = K('.ke-swfupload-body', self.div); + + function showError(itemDiv, msg) { + K('.ke-status > div', itemDiv).hide(); + K('.ke-message', itemDiv).addClass('ke-error').show().html(K.escape(msg)); + } + + var settings = { + debug : false, + upload_url : options.uploadUrl, + flash_url : options.flashUrl, + file_post_name : options.filePostName, + button_placeholder : K('.ke-swfupload-button > input', self.div)[0], + button_image_url: options.buttonImageUrl, + button_width: options.buttonWidth, + button_height: options.buttonHeight, + button_cursor : SWFUpload.CURSOR.HAND, + file_types : options.fileTypes, + file_types_description : options.fileTypesDesc, + file_upload_limit : options.fileUploadLimit, + file_size_limit : options.fileSizeLimit, + post_params : options.postParams, + file_queued_handler : function(file) { + file.url = self.options.fileIconUrl; + self.appendFile(file); + }, + file_queue_error_handler : function(file, errorCode, message) { + var errorName = ''; + switch (errorCode) { + case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED: + errorName = options.queueLimitExceeded; + break; + case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT: + errorName = options.fileExceedsSizeLimit; + break; + case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: + errorName = options.zeroByteFile; + break; + case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE: + errorName = options.invalidFiletype; + break; + default: + errorName = options.unknownError; + break; + } + K.DEBUG && alert(errorName); + }, + upload_start_handler : function(file) { + var self = this; + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv); + K('.ke-status > div', itemDiv).hide(); + K('.ke-progressbar', itemDiv).show(); + }, + upload_progress_handler : function(file, bytesLoaded, bytesTotal) { + var percent = Math.round(bytesLoaded * 100 / bytesTotal); + var progressbar = self.progressbars[file.id]; + progressbar.bar.css('width', Math.round(percent * 80 / 100) + 'px'); + progressbar.percent.html(percent + '%'); + }, + upload_error_handler : function(file, errorCode, message) { + if (file && file.filestatus == SWFUpload.FILE_STATUS.ERROR) { + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv).eq(0); + showError(itemDiv, self.options.errorMessage); + } + }, + upload_success_handler : function(file, serverData) { + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv).eq(0); + var data = {}; + try { + data = K.json(serverData); + } catch (e) { + self.options.afterError.call(this, '' + serverData + ''); + } + if (data.error !== 0) { + showError(itemDiv, K.DEBUG ? data.message : self.options.errorMessage); + return; + } + file.url = data.url; + K('.ke-img', itemDiv).attr('src', file.url).attr('data-status', file.filestatus).data('data', data); + K('.ke-status > div', itemDiv).hide(); + } + }; + self.swfu = new SWFUpload(settings); + + K('.ke-swfupload-startupload input', self.div).click(function() { + self.swfu.startUpload(); + }); + }, + getUrlList : function() { + var list = []; + K('.ke-img', self.bodyDiv).each(function() { + var img = K(this); + var status = img.attr('data-status'); + if (status == SWFUpload.FILE_STATUS.COMPLETE) { + list.push(img.data('data')); + } + }); + return list; + }, + removeFile : function(fileId) { + var self = this; + self.swfu.cancelUpload(fileId); + var itemDiv = K('div[data-id="' + fileId + '"]', self.bodyDiv); + K('.ke-photo', itemDiv).unbind(); + K('.ke-delete', itemDiv).unbind(); + itemDiv.remove(); + }, + removeFiles : function() { + var self = this; + K('.ke-item', self.bodyDiv).each(function() { + self.removeFile(K(this).attr('data-id')); + }); + }, + appendFile : function(file) { + var self = this; + var itemDiv = K('
'); + self.bodyDiv.append(itemDiv); + var photoDiv = K('
') + .mouseover(function(e) { + K(this).addClass('ke-on'); + }) + .mouseout(function(e) { + K(this).removeClass('ke-on'); + }); + itemDiv.append(photoDiv); + + var img = K('' + file.name + ''); + photoDiv.append(img); + K('').appendTo(photoDiv).click(function() { + self.removeFile(file.id); + }); + var statusDiv = K('
').appendTo(photoDiv); + // progressbar + K(['
', + '
', + '
0%
'].join('')).hide().appendTo(statusDiv); + // message + K('
' + self.options.pendingMessage + '
').appendTo(statusDiv); + + itemDiv.append('
' + file.name + '
'); + + self.progressbars[file.id] = { + bar : K('.ke-progressbar-bar-inner', photoDiv), + percent : K('.ke-progressbar-percent', photoDiv) + }; + }, + remove : function() { + this.removeFiles(); + this.swfu.destroy(); + this.div.html(''); + } +}); + +K.swfupload = function(element, options) { + return new KSWFUpload(element, options); +}; + +})(KindEditor); + +KindEditor.plugin('multiimage', function(K) { + var self = this, name = 'multiimage', + formatUploadUrl = K.undef(self.formatUploadUrl, true), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'), + imgPath = self.pluginsPath + 'multiimage/images/', + imageSizeLimit = K.undef(self.imageSizeLimit, '1MB'), + imageFileTypes = K.undef(self.imageFileTypes, '*.jpg;*.gif;*.png'), + imageUploadLimit = K.undef(self.imageUploadLimit, 20), + filePostName = K.undef(self.filePostName, 'imgFile'), + lang = self.lang(name + '.'); + + self.plugin.multiImageDialog = function(options) { + var clickFn = options.clickFn, + uploadDesc = K.tmpl(lang.uploadDesc, {uploadLimit : imageUploadLimit, sizeLimit : imageSizeLimit}); + var html = [ + '
', + '
', + '
', + '
' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : 650, + height : 510, + title : self.lang(name), + body : html, + previewBtn : { + name : lang.insertAll, + click : function(e) { + clickFn.call(self, swfupload.getUrlList()); + } + }, + yesBtn : { + name : lang.clearAll, + click : function(e) { + swfupload.removeFiles(); + } + }, + beforeRemove : function() { + // IE9 bugfix: https://github.com/kindsoft/kindeditor/issues/72 + if (!K.IE || K.V <= 8) { + swfupload.remove(); + } + } + }), + div = dialog.div; + + var swfupload = K.swfupload({ + container : K('.swfupload', div), + buttonImageUrl : imgPath + (self.langType == 'zh_CN' ? 'select-files-zh_CN.png' : 'select-files-en.png'), + buttonWidth : self.langType == 'zh_CN' ? 72 : 88, + buttonHeight : 23, + fileIconUrl : imgPath + 'image.png', + uploadDesc : uploadDesc, + startButtonValue : lang.startUpload, + uploadUrl : K.addParam(uploadJson, 'dir=image'), + flashUrl : imgPath + 'swfupload.swf', + filePostName : filePostName, + fileTypes : '*.jpg;*.jpeg;*.gif;*.png;*.bmp', + fileTypesDesc : 'Image Files', + fileUploadLimit : imageUploadLimit, + fileSizeLimit : imageSizeLimit, + postParams : K.undef(self.extraFileUploadParams, {}), + queueLimitExceeded : lang.queueLimitExceeded, + fileExceedsSizeLimit : lang.fileExceedsSizeLimit, + zeroByteFile : lang.zeroByteFile, + invalidFiletype : lang.invalidFiletype, + unknownError : lang.unknownError, + pendingMessage : lang.pending, + errorMessage : lang.uploadError, + afterError : function(html) { + self.errorDialog(html); + } + }); + + return dialog; + }; + self.clickToolbar(name, function() { + self.plugin.multiImageDialog({ + clickFn : function (urlList) { + if (urlList.length === 0) { + return; + } + K.each(urlList, function(i, data) { + if (self.afterUpload) { + self.afterUpload.call(self, data.url, data, 'multiimage'); + } + self.exec('insertimage', data.url, data.title, data.width, data.height, data.border, data.align); + }); + // Bugfix: [Firefox] 上传图片后,总是出现正在加载的样式,需要延迟执行hideDialog + setTimeout(function() { + self.hideDialog().focus(); + }, 0); + } + }); + }); +}); + + +/** + * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com + * + * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/ + * + * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilz閚 and Mammon Media and is released under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + */ + + +/* ******************* */ +/* Constructor & Init */ +/* ******************* */ + +(function() { + +window.SWFUpload = function (settings) { + this.initSWFUpload(settings); +}; + +SWFUpload.prototype.initSWFUpload = function (settings) { + try { + this.customSettings = {}; // A container where developers can place their own settings associated with this instance. + this.settings = settings; + this.eventQueue = []; + this.movieName = "KindEditor_SWFUpload_" + SWFUpload.movieCount++; + this.movieElement = null; + + + // Setup global control tracking + SWFUpload.instances[this.movieName] = this; + + // Load the settings. Load the Flash movie. + this.initSettings(); + this.loadFlash(); + this.displayDebugInfo(); + } catch (ex) { + delete SWFUpload.instances[this.movieName]; + throw ex; + } +}; + +/* *************** */ +/* Static Members */ +/* *************** */ +SWFUpload.instances = {}; +SWFUpload.movieCount = 0; +SWFUpload.version = "2.2.0 2009-03-25"; +SWFUpload.QUEUE_ERROR = { + QUEUE_LIMIT_EXCEEDED : -100, + FILE_EXCEEDS_SIZE_LIMIT : -110, + ZERO_BYTE_FILE : -120, + INVALID_FILETYPE : -130 +}; +SWFUpload.UPLOAD_ERROR = { + HTTP_ERROR : -200, + MISSING_UPLOAD_URL : -210, + IO_ERROR : -220, + SECURITY_ERROR : -230, + UPLOAD_LIMIT_EXCEEDED : -240, + UPLOAD_FAILED : -250, + SPECIFIED_FILE_ID_NOT_FOUND : -260, + FILE_VALIDATION_FAILED : -270, + FILE_CANCELLED : -280, + UPLOAD_STOPPED : -290 +}; +SWFUpload.FILE_STATUS = { + QUEUED : -1, + IN_PROGRESS : -2, + ERROR : -3, + COMPLETE : -4, + CANCELLED : -5 +}; +SWFUpload.BUTTON_ACTION = { + SELECT_FILE : -100, + SELECT_FILES : -110, + START_UPLOAD : -120 +}; +SWFUpload.CURSOR = { + ARROW : -1, + HAND : -2 +}; +SWFUpload.WINDOW_MODE = { + WINDOW : "window", + TRANSPARENT : "transparent", + OPAQUE : "opaque" +}; + +// Private: takes a URL, determines if it is relative and converts to an absolute URL +// using the current site. Only processes the URL if it can, otherwise returns the URL untouched +SWFUpload.completeURL = function(url) { + if (typeof(url) !== "string" || url.match(/^https?:\/\//i) || url.match(/^\//)) { + return url; + } + + var currentURL = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : ""); + + var indexSlash = window.location.pathname.lastIndexOf("/"); + if (indexSlash <= 0) { + path = "/"; + } else { + path = window.location.pathname.substr(0, indexSlash) + "/"; + } + + return /*currentURL +*/ path + url; + +}; + + +/* ******************** */ +/* Instance Members */ +/* ******************** */ + +// Private: initSettings ensures that all the +// settings are set, getting a default value if one was not assigned. +SWFUpload.prototype.initSettings = function () { + this.ensureDefault = function (settingName, defaultValue) { + this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName]; + }; + + // Upload backend settings + this.ensureDefault("upload_url", ""); + this.ensureDefault("preserve_relative_urls", false); + this.ensureDefault("file_post_name", "Filedata"); + this.ensureDefault("post_params", {}); + this.ensureDefault("use_query_string", false); + this.ensureDefault("requeue_on_error", false); + this.ensureDefault("http_success", []); + this.ensureDefault("assume_success_timeout", 0); + + // File Settings + this.ensureDefault("file_types", "*.*"); + this.ensureDefault("file_types_description", "All Files"); + this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited" + this.ensureDefault("file_upload_limit", 0); + this.ensureDefault("file_queue_limit", 0); + + // Flash Settings + this.ensureDefault("flash_url", "swfupload.swf"); + this.ensureDefault("prevent_swf_caching", true); + + // Button Settings + this.ensureDefault("button_image_url", ""); + this.ensureDefault("button_width", 1); + this.ensureDefault("button_height", 1); + this.ensureDefault("button_text", ""); + this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;"); + this.ensureDefault("button_text_top_padding", 0); + this.ensureDefault("button_text_left_padding", 0); + this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES); + this.ensureDefault("button_disabled", false); + this.ensureDefault("button_placeholder_id", ""); + this.ensureDefault("button_placeholder", null); + this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW); + this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW); + + // Debug Settings + this.ensureDefault("debug", false); + this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API + + // Event Handlers + this.settings.return_upload_start_handler = this.returnUploadStart; + this.ensureDefault("swfupload_loaded_handler", null); + this.ensureDefault("file_dialog_start_handler", null); + this.ensureDefault("file_queued_handler", null); + this.ensureDefault("file_queue_error_handler", null); + this.ensureDefault("file_dialog_complete_handler", null); + + this.ensureDefault("upload_start_handler", null); + this.ensureDefault("upload_progress_handler", null); + this.ensureDefault("upload_error_handler", null); + this.ensureDefault("upload_success_handler", null); + this.ensureDefault("upload_complete_handler", null); + + this.ensureDefault("debug_handler", this.debugMessage); + + this.ensureDefault("custom_settings", {}); + + // Other settings + this.customSettings = this.settings.custom_settings; + + // Update the flash url if needed + if (!!this.settings.prevent_swf_caching) { + this.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime(); + } + + if (!this.settings.preserve_relative_urls) { + //this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url); // Don't need to do this one since flash doesn't look at it + this.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url); + this.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url); + } + + delete this.ensureDefault; +}; + +// Private: loadFlash replaces the button_placeholder element with the flash movie. +SWFUpload.prototype.loadFlash = function () { + var targetElement, tempParent; + + // Make sure an element with the ID we are going to use doesn't already exist + if (document.getElementById(this.movieName) !== null) { + throw "ID " + this.movieName + " is already in use. The Flash Object could not be added"; + } + + // Get the element where we will be placing the flash movie + targetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder; + + if (targetElement == undefined) { + throw "Could not find the placeholder element: " + this.settings.button_placeholder_id; + } + + // Append the container and load the flash + tempParent = document.createElement("div"); + tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers) + targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement); + + // Fix IE Flash/Form bug + if (window[this.movieName] == undefined) { + window[this.movieName] = this.getMovieElement(); + } + +}; + +// Private: getFlashHTML generates the object tag needed to embed the flash in to the document +SWFUpload.prototype.getFlashHTML = function () { + // Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay + // Fix bug for IE9 + // http://www.kindsoft.net/view.php?bbsid=7&postid=5825&pagenum=1 + var classid = ''; + if (KindEditor.IE && KindEditor.V > 8) { + classid = ' classid = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"'; + } + return ['', + '', + '', + '', + '', + '', + '', + ''].join(""); +}; + +// Private: getFlashVars builds the parameter string that will be passed +// to flash in the flashvars param. +SWFUpload.prototype.getFlashVars = function () { + // Build a string from the post param object + var paramString = this.buildParamString(); + var httpSuccessString = this.settings.http_success.join(","); + + // Build the parameter string + return ["movieName=", encodeURIComponent(this.movieName), + "&uploadURL=", encodeURIComponent(this.settings.upload_url), + "&useQueryString=", encodeURIComponent(this.settings.use_query_string), + "&requeueOnError=", encodeURIComponent(this.settings.requeue_on_error), + "&httpSuccess=", encodeURIComponent(httpSuccessString), + "&assumeSuccessTimeout=", encodeURIComponent(this.settings.assume_success_timeout), + "&params=", encodeURIComponent(paramString), + "&filePostName=", encodeURIComponent(this.settings.file_post_name), + "&fileTypes=", encodeURIComponent(this.settings.file_types), + "&fileTypesDescription=", encodeURIComponent(this.settings.file_types_description), + "&fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit), + "&fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit), + "&fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit), + "&debugEnabled=", encodeURIComponent(this.settings.debug_enabled), + "&buttonImageURL=", encodeURIComponent(this.settings.button_image_url), + "&buttonWidth=", encodeURIComponent(this.settings.button_width), + "&buttonHeight=", encodeURIComponent(this.settings.button_height), + "&buttonText=", encodeURIComponent(this.settings.button_text), + "&buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding), + "&buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding), + "&buttonTextStyle=", encodeURIComponent(this.settings.button_text_style), + "&buttonAction=", encodeURIComponent(this.settings.button_action), + "&buttonDisabled=", encodeURIComponent(this.settings.button_disabled), + "&buttonCursor=", encodeURIComponent(this.settings.button_cursor) + ].join(""); +}; + +// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload +// The element is cached after the first lookup +SWFUpload.prototype.getMovieElement = function () { + if (this.movieElement == undefined) { + this.movieElement = document.getElementById(this.movieName); + } + + if (this.movieElement === null) { + throw "Could not find Flash element"; + } + + return this.movieElement; +}; + +// Private: buildParamString takes the name/value pairs in the post_params setting object +// and joins them up in to a string formatted "name=value&name=value" +SWFUpload.prototype.buildParamString = function () { + var postParams = this.settings.post_params; + var paramStringPairs = []; + + if (typeof(postParams) === "object") { + for (var name in postParams) { + if (postParams.hasOwnProperty(name)) { + paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString())); + } + } + } + + return paramStringPairs.join("&"); +}; + +// Public: Used to remove a SWFUpload instance from the page. This method strives to remove +// all references to the SWF, and other objects so memory is properly freed. +// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state. +// Credits: Major improvements provided by steffen +SWFUpload.prototype.destroy = function () { + try { + // Make sure Flash is done before we try to remove it + this.cancelUpload(null, false); + + + // Remove the SWFUpload DOM nodes + var movieElement = null; + movieElement = this.getMovieElement(); + + if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE + // Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround) + for (var i in movieElement) { + try { + if (typeof(movieElement[i]) === "function") { + movieElement[i] = null; + } + } catch (ex1) {} + } + + // Remove the Movie Element from the page + try { + movieElement.parentNode.removeChild(movieElement); + } catch (ex) {} + } + + // Remove IE form fix reference + window[this.movieName] = null; + + // Destroy other references + SWFUpload.instances[this.movieName] = null; + delete SWFUpload.instances[this.movieName]; + + this.movieElement = null; + this.settings = null; + this.customSettings = null; + this.eventQueue = null; + this.movieName = null; + + + return true; + } catch (ex2) { + return false; + } +}; + + +// Public: displayDebugInfo prints out settings and configuration +// information about this SWFUpload instance. +// This function (and any references to it) can be deleted when placing +// SWFUpload in production. +SWFUpload.prototype.displayDebugInfo = function () { + this.debug( + [ + "---SWFUpload Instance Info---\n", + "Version: ", SWFUpload.version, "\n", + "Movie Name: ", this.movieName, "\n", + "Settings:\n", + "\t", "upload_url: ", this.settings.upload_url, "\n", + "\t", "flash_url: ", this.settings.flash_url, "\n", + "\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n", + "\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n", + "\t", "http_success: ", this.settings.http_success.join(", "), "\n", + "\t", "assume_success_timeout: ", this.settings.assume_success_timeout, "\n", + "\t", "file_post_name: ", this.settings.file_post_name, "\n", + "\t", "post_params: ", this.settings.post_params.toString(), "\n", + "\t", "file_types: ", this.settings.file_types, "\n", + "\t", "file_types_description: ", this.settings.file_types_description, "\n", + "\t", "file_size_limit: ", this.settings.file_size_limit, "\n", + "\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n", + "\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n", + "\t", "debug: ", this.settings.debug.toString(), "\n", + + "\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n", + + "\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n", + "\t", "button_placeholder: ", (this.settings.button_placeholder ? "Set" : "Not Set"), "\n", + "\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n", + "\t", "button_width: ", this.settings.button_width.toString(), "\n", + "\t", "button_height: ", this.settings.button_height.toString(), "\n", + "\t", "button_text: ", this.settings.button_text.toString(), "\n", + "\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n", + "\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n", + "\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n", + "\t", "button_action: ", this.settings.button_action.toString(), "\n", + "\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n", + + "\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n", + "Event Handlers:\n", + "\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n", + "\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n", + "\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n", + "\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n", + "\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n", + "\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n", + "\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n", + "\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n", + "\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n", + "\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n" + ].join("") + ); +}; + +/* Note: addSetting and getSetting are no longer used by SWFUpload but are included + the maintain v2 API compatibility +*/ +// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used. +SWFUpload.prototype.addSetting = function (name, value, default_value) { + if (value == undefined) { + return (this.settings[name] = default_value); + } else { + return (this.settings[name] = value); + } +}; + +// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found. +SWFUpload.prototype.getSetting = function (name) { + if (this.settings[name] != undefined) { + return this.settings[name]; + } + + return ""; +}; + + + +// Private: callFlash handles function calls made to the Flash element. +// Calls are made with a setTimeout for some functions to work around +// bugs in the ExternalInterface library. +SWFUpload.prototype.callFlash = function (functionName, argumentArray) { + argumentArray = argumentArray || []; + + var movieElement = this.getMovieElement(); + var returnValue, returnString; + + // Flash's method if calling ExternalInterface methods (code adapted from MooTools). + try { + returnString = movieElement.CallFunction('' + __flash__argumentsToXML(argumentArray, 0) + ''); + returnValue = eval(returnString); + } catch (ex) { + throw "Call to " + functionName + " failed"; + } + + // Unescape file post param values + if (returnValue != undefined && typeof returnValue.post === "object") { + returnValue = this.unescapeFilePostParams(returnValue); + } + + return returnValue; +}; + +/* ***************************** + -- Flash control methods -- + Your UI should use these + to operate SWFUpload + ***************************** */ + +// WARNING: this function does not work in Flash Player 10 +// Public: selectFile causes a File Selection Dialog window to appear. This +// dialog only allows 1 file to be selected. +SWFUpload.prototype.selectFile = function () { + this.callFlash("SelectFile"); +}; + +// WARNING: this function does not work in Flash Player 10 +// Public: selectFiles causes a File Selection Dialog window to appear/ This +// dialog allows the user to select any number of files +// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names. +// If the selection name length is too long the dialog will fail in an unpredictable manner. There is no work-around +// for this bug. +SWFUpload.prototype.selectFiles = function () { + this.callFlash("SelectFiles"); +}; + + +// Public: startUpload starts uploading the first file in the queue unless +// the optional parameter 'fileID' specifies the ID +SWFUpload.prototype.startUpload = function (fileID) { + this.callFlash("StartUpload", [fileID]); +}; + +// Public: cancelUpload cancels any queued file. The fileID parameter may be the file ID or index. +// If you do not specify a fileID the current uploading file or first file in the queue is cancelled. +// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter. +SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) { + if (triggerErrorEvent !== false) { + triggerErrorEvent = true; + } + this.callFlash("CancelUpload", [fileID, triggerErrorEvent]); +}; + +// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue. +// If nothing is currently uploading then nothing happens. +SWFUpload.prototype.stopUpload = function () { + this.callFlash("StopUpload"); +}; + +/* ************************ + * Settings methods + * These methods change the SWFUpload settings. + * SWFUpload settings should not be changed directly on the settings object + * since many of the settings need to be passed to Flash in order to take + * effect. + * *********************** */ + +// Public: getStats gets the file statistics object. +SWFUpload.prototype.getStats = function () { + return this.callFlash("GetStats"); +}; + +// Public: setStats changes the SWFUpload statistics. You shouldn't need to +// change the statistics but you can. Changing the statistics does not +// affect SWFUpload accept for the successful_uploads count which is used +// by the upload_limit setting to determine how many files the user may upload. +SWFUpload.prototype.setStats = function (statsObject) { + this.callFlash("SetStats", [statsObject]); +}; + +// Public: getFile retrieves a File object by ID or Index. If the file is +// not found then 'null' is returned. +SWFUpload.prototype.getFile = function (fileID) { + if (typeof(fileID) === "number") { + return this.callFlash("GetFileByIndex", [fileID]); + } else { + return this.callFlash("GetFile", [fileID]); + } +}; + +// Public: addFileParam sets a name/value pair that will be posted with the +// file specified by the Files ID. If the name already exists then the +// exiting value will be overwritten. +SWFUpload.prototype.addFileParam = function (fileID, name, value) { + return this.callFlash("AddFileParam", [fileID, name, value]); +}; + +// Public: removeFileParam removes a previously set (by addFileParam) name/value +// pair from the specified file. +SWFUpload.prototype.removeFileParam = function (fileID, name) { + this.callFlash("RemoveFileParam", [fileID, name]); +}; + +// Public: setUploadUrl changes the upload_url setting. +SWFUpload.prototype.setUploadURL = function (url) { + this.settings.upload_url = url.toString(); + this.callFlash("SetUploadURL", [url]); +}; + +// Public: setPostParams changes the post_params setting +SWFUpload.prototype.setPostParams = function (paramsObject) { + this.settings.post_params = paramsObject; + this.callFlash("SetPostParams", [paramsObject]); +}; + +// Public: addPostParam adds post name/value pair. Each name can have only one value. +SWFUpload.prototype.addPostParam = function (name, value) { + this.settings.post_params[name] = value; + this.callFlash("SetPostParams", [this.settings.post_params]); +}; + +// Public: removePostParam deletes post name/value pair. +SWFUpload.prototype.removePostParam = function (name) { + delete this.settings.post_params[name]; + this.callFlash("SetPostParams", [this.settings.post_params]); +}; + +// Public: setFileTypes changes the file_types setting and the file_types_description setting +SWFUpload.prototype.setFileTypes = function (types, description) { + this.settings.file_types = types; + this.settings.file_types_description = description; + this.callFlash("SetFileTypes", [types, description]); +}; + +// Public: setFileSizeLimit changes the file_size_limit setting +SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) { + this.settings.file_size_limit = fileSizeLimit; + this.callFlash("SetFileSizeLimit", [fileSizeLimit]); +}; + +// Public: setFileUploadLimit changes the file_upload_limit setting +SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) { + this.settings.file_upload_limit = fileUploadLimit; + this.callFlash("SetFileUploadLimit", [fileUploadLimit]); +}; + +// Public: setFileQueueLimit changes the file_queue_limit setting +SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) { + this.settings.file_queue_limit = fileQueueLimit; + this.callFlash("SetFileQueueLimit", [fileQueueLimit]); +}; + +// Public: setFilePostName changes the file_post_name setting +SWFUpload.prototype.setFilePostName = function (filePostName) { + this.settings.file_post_name = filePostName; + this.callFlash("SetFilePostName", [filePostName]); +}; + +// Public: setUseQueryString changes the use_query_string setting +SWFUpload.prototype.setUseQueryString = function (useQueryString) { + this.settings.use_query_string = useQueryString; + this.callFlash("SetUseQueryString", [useQueryString]); +}; + +// Public: setRequeueOnError changes the requeue_on_error setting +SWFUpload.prototype.setRequeueOnError = function (requeueOnError) { + this.settings.requeue_on_error = requeueOnError; + this.callFlash("SetRequeueOnError", [requeueOnError]); +}; + +// Public: setHTTPSuccess changes the http_success setting +SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) { + if (typeof http_status_codes === "string") { + http_status_codes = http_status_codes.replace(" ", "").split(","); + } + + this.settings.http_success = http_status_codes; + this.callFlash("SetHTTPSuccess", [http_status_codes]); +}; + +// Public: setHTTPSuccess changes the http_success setting +SWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) { + this.settings.assume_success_timeout = timeout_seconds; + this.callFlash("SetAssumeSuccessTimeout", [timeout_seconds]); +}; + +// Public: setDebugEnabled changes the debug_enabled setting +SWFUpload.prototype.setDebugEnabled = function (debugEnabled) { + this.settings.debug_enabled = debugEnabled; + this.callFlash("SetDebugEnabled", [debugEnabled]); +}; + +// Public: setButtonImageURL loads a button image sprite +SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) { + if (buttonImageURL == undefined) { + buttonImageURL = ""; + } + + this.settings.button_image_url = buttonImageURL; + this.callFlash("SetButtonImageURL", [buttonImageURL]); +}; + +// Public: setButtonDimensions resizes the Flash Movie and button +SWFUpload.prototype.setButtonDimensions = function (width, height) { + this.settings.button_width = width; + this.settings.button_height = height; + + var movie = this.getMovieElement(); + if (movie != undefined) { + movie.style.width = width + "px"; + movie.style.height = height + "px"; + } + + this.callFlash("SetButtonDimensions", [width, height]); +}; +// Public: setButtonText Changes the text overlaid on the button +SWFUpload.prototype.setButtonText = function (html) { + this.settings.button_text = html; + this.callFlash("SetButtonText", [html]); +}; +// Public: setButtonTextPadding changes the top and left padding of the text overlay +SWFUpload.prototype.setButtonTextPadding = function (left, top) { + this.settings.button_text_top_padding = top; + this.settings.button_text_left_padding = left; + this.callFlash("SetButtonTextPadding", [left, top]); +}; + +// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button +SWFUpload.prototype.setButtonTextStyle = function (css) { + this.settings.button_text_style = css; + this.callFlash("SetButtonTextStyle", [css]); +}; +// Public: setButtonDisabled disables/enables the button +SWFUpload.prototype.setButtonDisabled = function (isDisabled) { + this.settings.button_disabled = isDisabled; + this.callFlash("SetButtonDisabled", [isDisabled]); +}; +// Public: setButtonAction sets the action that occurs when the button is clicked +SWFUpload.prototype.setButtonAction = function (buttonAction) { + this.settings.button_action = buttonAction; + this.callFlash("SetButtonAction", [buttonAction]); +}; + +// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button +SWFUpload.prototype.setButtonCursor = function (cursor) { + this.settings.button_cursor = cursor; + this.callFlash("SetButtonCursor", [cursor]); +}; + +/* ******************************* + Flash Event Interfaces + These functions are used by Flash to trigger the various + events. + + All these functions a Private. + + Because the ExternalInterface library is buggy the event calls + are added to a queue and the queue then executed by a setTimeout. + This ensures that events are executed in a determinate order and that + the ExternalInterface bugs are avoided. +******************************* */ + +SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + + if (argumentArray == undefined) { + argumentArray = []; + } else if (!(argumentArray instanceof Array)) { + argumentArray = [argumentArray]; + } + + var self = this; + if (typeof this.settings[handlerName] === "function") { + // Queue the event + this.eventQueue.push(function () { + this.settings[handlerName].apply(this, argumentArray); + }); + + // Execute the next queued event + setTimeout(function () { + self.executeNextEvent(); + }, 0); + + } else if (this.settings[handlerName] !== null) { + throw "Event handler " + handlerName + " is unknown or is not a function"; + } +}; + +// Private: Causes the next event in the queue to be executed. Since events are queued using a setTimeout +// we must queue them in order to garentee that they are executed in order. +SWFUpload.prototype.executeNextEvent = function () { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + + var f = this.eventQueue ? this.eventQueue.shift() : null; + if (typeof(f) === "function") { + f.apply(this); + } +}; + +// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have +// properties that contain characters that are not valid for JavaScript identifiers. To work around this +// the Flash Component escapes the parameter names and we must unescape again before passing them along. +SWFUpload.prototype.unescapeFilePostParams = function (file) { + var reg = /[$]([0-9a-f]{4})/i; + var unescapedPost = {}; + var uk; + + if (file != undefined) { + for (var k in file.post) { + if (file.post.hasOwnProperty(k)) { + uk = k; + var match; + while ((match = reg.exec(uk)) !== null) { + uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16))); + } + unescapedPost[uk] = file.post[k]; + } + } + + file.post = unescapedPost; + } + + return file; +}; + +// Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working) +SWFUpload.prototype.testExternalInterface = function () { + try { + return this.callFlash("TestExternalInterface"); + } catch (ex) { + return false; + } +}; + +// Private: This event is called by Flash when it has finished loading. Don't modify this. +// Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded. +SWFUpload.prototype.flashReady = function () { + // Check that the movie element is loaded correctly with its ExternalInterface methods defined + var movieElement = this.getMovieElement(); + + if (!movieElement) { + this.debug("Flash called back ready but the flash movie can't be found."); + return; + } + + this.cleanUp(movieElement); + + this.queueEvent("swfupload_loaded_handler"); +}; + +// Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE. +// This function is called by Flash each time the ExternalInterface functions are created. +SWFUpload.prototype.cleanUp = function (movieElement) { + // Pro-actively unhook all the Flash functions + try { + if (this.movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE + this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)"); + for (var key in movieElement) { + try { + if (typeof(movieElement[key]) === "function") { + movieElement[key] = null; + } + } catch (ex) { + } + } + } + } catch (ex1) { + + } + + // Fix Flashes own cleanup code so if the SWFMovie was removed from the page + // it doesn't display errors. + window["__flash__removeCallback"] = function (instance, name) { + try { + if (instance) { + instance[name] = null; + } + } catch (flashEx) { + + } + }; + +}; + + +/* This is a chance to do something before the browse window opens */ +SWFUpload.prototype.fileDialogStart = function () { + this.queueEvent("file_dialog_start_handler"); +}; + + +/* Called when a file is successfully added to the queue. */ +SWFUpload.prototype.fileQueued = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("file_queued_handler", file); +}; + + +/* Handle errors that occur when an attempt to queue a file fails. */ +SWFUpload.prototype.fileQueueError = function (file, errorCode, message) { + file = this.unescapeFilePostParams(file); + this.queueEvent("file_queue_error_handler", [file, errorCode, message]); +}; + +/* Called after the file dialog has closed and the selected files have been queued. + You could call startUpload here if you want the queued files to begin uploading immediately. */ +SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) { + this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued, numFilesInQueue]); +}; + +SWFUpload.prototype.uploadStart = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("return_upload_start_handler", file); +}; + +SWFUpload.prototype.returnUploadStart = function (file) { + var returnValue; + if (typeof this.settings.upload_start_handler === "function") { + file = this.unescapeFilePostParams(file); + returnValue = this.settings.upload_start_handler.call(this, file); + } else if (this.settings.upload_start_handler != undefined) { + throw "upload_start_handler must be a function"; + } + + // Convert undefined to true so if nothing is returned from the upload_start_handler it is + // interpretted as 'true'. + if (returnValue === undefined) { + returnValue = true; + } + + returnValue = !!returnValue; + + this.callFlash("ReturnUploadStart", [returnValue]); +}; + + + +SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]); +}; + +SWFUpload.prototype.uploadError = function (file, errorCode, message) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_error_handler", [file, errorCode, message]); +}; + +SWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_success_handler", [file, serverData, responseReceived]); +}; + +SWFUpload.prototype.uploadComplete = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_complete_handler", file); +}; + +/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the + internal debug console. You can override this event and have messages written where you want. */ +SWFUpload.prototype.debug = function (message) { + this.queueEvent("debug_handler", message); +}; + + +/* ********************************** + Debug Console + The debug console is a self contained, in page location + for debug message to be sent. The Debug Console adds + itself to the body if necessary. + + The console is automatically scrolled as messages appear. + + If you are using your own debug handler or when you deploy to production and + have debug disabled you can remove these functions to reduce the file size + and complexity. +********************************** */ + +// Private: debugMessage is the default debug_handler. If you want to print debug messages +// call the debug() function. When overriding the function your own function should +// check to see if the debug setting is true before outputting debug information. +SWFUpload.prototype.debugMessage = function (message) { + if (this.settings.debug) { + var exceptionMessage, exceptionValues = []; + + // Check for an exception object and print it nicely + if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") { + for (var key in message) { + if (message.hasOwnProperty(key)) { + exceptionValues.push(key + ": " + message[key]); + } + } + exceptionMessage = exceptionValues.join("\n") || ""; + exceptionValues = exceptionMessage.split("\n"); + exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: "); + SWFUpload.Console.writeLine(exceptionMessage); + } else { + SWFUpload.Console.writeLine(message); + } + } +}; + +SWFUpload.Console = {}; +SWFUpload.Console.writeLine = function (message) { + var console, documentForm; + + try { + console = document.getElementById("SWFUpload_Console"); + + if (!console) { + documentForm = document.createElement("form"); + document.getElementsByTagName("body")[0].appendChild(documentForm); + + console = document.createElement("textarea"); + console.id = "SWFUpload_Console"; + console.style.fontFamily = "monospace"; + console.setAttribute("wrap", "off"); + console.wrap = "off"; + console.style.overflow = "auto"; + console.style.width = "700px"; + console.style.height = "350px"; + console.style.margin = "5px"; + documentForm.appendChild(console); + } + + console.value += message + "\n"; + + console.scrollTop = console.scrollHeight - console.clientHeight; + } catch (ex) { + alert("Exception: " + ex.name + " Message: " + ex.message); + } +}; + +})(); + +(function() { +/* + Queue Plug-in + + Features: + *Adds a cancelQueue() method for cancelling the entire queue. + *All queued files are uploaded when startUpload() is called. + *If false is returned from uploadComplete then the queue upload is stopped. + If false is not returned (strict comparison) then the queue upload is continued. + *Adds a QueueComplete event that is fired when all the queued files have finished uploading. + Set the event handler with the queue_complete_handler setting. + + */ + +if (typeof(SWFUpload) === "function") { + SWFUpload.queue = {}; + + SWFUpload.prototype.initSettings = (function (oldInitSettings) { + return function () { + if (typeof(oldInitSettings) === "function") { + oldInitSettings.call(this); + } + + this.queueSettings = {}; + + this.queueSettings.queue_cancelled_flag = false; + this.queueSettings.queue_upload_count = 0; + + this.queueSettings.user_upload_complete_handler = this.settings.upload_complete_handler; + this.queueSettings.user_upload_start_handler = this.settings.upload_start_handler; + this.settings.upload_complete_handler = SWFUpload.queue.uploadCompleteHandler; + this.settings.upload_start_handler = SWFUpload.queue.uploadStartHandler; + + this.settings.queue_complete_handler = this.settings.queue_complete_handler || null; + }; + })(SWFUpload.prototype.initSettings); + + SWFUpload.prototype.startUpload = function (fileID) { + this.queueSettings.queue_cancelled_flag = false; + this.callFlash("StartUpload", [fileID]); + }; + + SWFUpload.prototype.cancelQueue = function () { + this.queueSettings.queue_cancelled_flag = true; + this.stopUpload(); + + var stats = this.getStats(); + while (stats.files_queued > 0) { + this.cancelUpload(); + stats = this.getStats(); + } + }; + + SWFUpload.queue.uploadStartHandler = function (file) { + var returnValue; + if (typeof(this.queueSettings.user_upload_start_handler) === "function") { + returnValue = this.queueSettings.user_upload_start_handler.call(this, file); + } + + // To prevent upload a real "FALSE" value must be returned, otherwise default to a real "TRUE" value. + returnValue = (returnValue === false) ? false : true; + + this.queueSettings.queue_cancelled_flag = !returnValue; + + return returnValue; + }; + + SWFUpload.queue.uploadCompleteHandler = function (file) { + var user_upload_complete_handler = this.queueSettings.user_upload_complete_handler; + var continueUpload; + + if (file.filestatus === SWFUpload.FILE_STATUS.COMPLETE) { + this.queueSettings.queue_upload_count++; + } + + if (typeof(user_upload_complete_handler) === "function") { + continueUpload = (user_upload_complete_handler.call(this, file) === false) ? false : true; + } else if (file.filestatus === SWFUpload.FILE_STATUS.QUEUED) { + // If the file was stopped and re-queued don't restart the upload + continueUpload = false; + } else { + continueUpload = true; + } + + if (continueUpload) { + var stats = this.getStats(); + if (stats.files_queued > 0 && this.queueSettings.queue_cancelled_flag === false) { + this.startUpload(); + } else if (this.queueSettings.queue_cancelled_flag === false) { + this.queueEvent("queue_complete_handler", [this.queueSettings.queue_upload_count]); + this.queueSettings.queue_upload_count = 0; + } else { + this.queueSettings.queue_cancelled_flag = false; + this.queueSettings.queue_upload_count = 0; + } + } + }; +} + +})(); diff --git a/web/resource/components/kindeditor/plugins/pagebreak/pagebreak.js b/web/resource/components/kindeditor/plugins/pagebreak/pagebreak.js new file mode 100644 index 0000000..dfa883a --- /dev/null +++ b/web/resource/components/kindeditor/plugins/pagebreak/pagebreak.js @@ -0,0 +1,27 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('pagebreak', function(K) { + var self = this; + var name = 'pagebreak'; + var pagebreakHtml = K.undef(self.pagebreakHtml, '
'); + + self.clickToolbar(name, function() { + var cmd = self.cmd, range = cmd.range; + self.focus(); + var tail = self.newlineTag == 'br' || K.WEBKIT ? '' : ''; + self.insertHtml(pagebreakHtml + tail); + if (tail !== '') { + var p = K('#__kindeditor_tail_tag__', self.edit.doc); + range.selectNodeContents(p[0]); + p.removeAttr('id'); + cmd.select(); + } + }); +}); diff --git a/web/resource/components/kindeditor/plugins/plainpaste/plainpaste.js b/web/resource/components/kindeditor/plugins/plainpaste/plainpaste.js new file mode 100644 index 0000000..8f7bed8 --- /dev/null +++ b/web/resource/components/kindeditor/plugins/plainpaste/plainpaste.js @@ -0,0 +1,41 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('plainpaste', function(K) { + var self = this, name = 'plainpaste'; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = '
' + + '
' + lang.comment + '
' + + '' + + '
', + dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var html = textarea.val(); + html = K.escape(html); + html = html.replace(/ {2}/g, '  '); + if (self.newlineTag == 'p') { + html = html.replace(/^/, '

').replace(/$/, '

').replace(/\n/g, '

'); + } else { + html = html.replace(/\n/g, '
$&'); + } + self.insertHtml(html).hideDialog().focus(); + } + } + }), + textarea = K('textarea', dialog.div); + textarea[0].focus(); + }); +}); diff --git a/web/resource/components/kindeditor/plugins/preview/preview.js b/web/resource/components/kindeditor/plugins/preview/preview.js new file mode 100644 index 0000000..ef6e2cf --- /dev/null +++ b/web/resource/components/kindeditor/plugins/preview/preview.js @@ -0,0 +1,31 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('preview', function(K) { + var self = this, name = 'preview', undefined; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = '

' + + '' + + '
', + dialog = self.createDialog({ + name : name, + width : 750, + title : self.lang(name), + body : html + }), + iframe = K('iframe', dialog.div), + doc = K.iframeDoc(iframe); + doc.open(); + doc.write(self.fullHtml()); + doc.close(); + K(doc.body).css('background-color', '#FFF'); + iframe[0].contentWindow.focus(); + }); +}); diff --git a/web/resource/components/kindeditor/plugins/quickformat/quickformat.js b/web/resource/components/kindeditor/plugins/quickformat/quickformat.js new file mode 100644 index 0000000..5b98c72 --- /dev/null +++ b/web/resource/components/kindeditor/plugins/quickformat/quickformat.js @@ -0,0 +1,81 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('quickformat', function(K) { + var self = this, name = 'quickformat', + blockMap = K.toMap('blockquote,center,div,h1,h2,h3,h4,h5,h6,p'); + function getFirstChild(knode) { + var child = knode.first(); + while (child && child.first()) { + child = child.first(); + } + return child; + } + self.clickToolbar(name, function() { + self.focus(); + var doc = self.edit.doc, + range = self.cmd.range, + child = K(doc.body).first(), next, + nodeList = [], subList = [], + bookmark = range.createBookmark(true); + while(child) { + next = child.next(); + var firstChild = getFirstChild(child); + if (!firstChild || firstChild.name != 'img') { + if (blockMap[child.name]) { + child.html(child.html().replace(/^(\s| | )+/ig, '')); + child.css('text-indent', '2em'); + } else { + subList.push(child); + } + if (!next || (blockMap[next.name] || blockMap[child.name] && !blockMap[next.name])) { + if (subList.length > 0) { + nodeList.push(subList); + } + subList = []; + } + } + child = next; + } + K.each(nodeList, function(i, subList) { + var wrapper = K('

', doc); + subList[0].before(wrapper); + K.each(subList, function(i, knode) { + wrapper.append(knode); + }); + }); + range.moveToBookmark(bookmark); + self.addBookmark(); + }); +}); + +/** +-------------------------- +abcd
+1234
+ +to + +

+ abcd
+ 1234
+

+ +-------------------------- + +  abcd1233 +

1234

+ +to + +

abcd1233

+

1234

+ +-------------------------- +*/ \ No newline at end of file diff --git a/web/resource/components/kindeditor/themes/qq/qq.css b/web/resource/components/kindeditor/themes/qq/qq.css new file mode 100644 index 0000000..a45e08c --- /dev/null +++ b/web/resource/components/kindeditor/themes/qq/qq.css @@ -0,0 +1,143 @@ +/* container */ +.ke-container-qq { + display: block; + border: 1px solid #c3c3c3; + background-color: #FFF; + overflow: hidden; + margin: 0; + padding: 0; +} +/* toolbar */ +.ke-container-qq .ke-toolbar { + border-bottom: 1px solid #c3c3c3; + background-color: #FFFFFF; + padding: 2px 5px; + text-align: left; + overflow: hidden; + zoom: 1; +} +.ke-toolbar-icon-url { + background-image: url(editor.gif); + width:18px; + *xwidth:20px; + height:18px; + *xheight:20px; +} +.ke-icon-checked{ + background-image: url(../default/default.png); + width:16px; + height:16px; +} +.ke-container-qq .ke-icon-bold{ + background-position: 4px 1px; +} +.ke-container-qq .ke-icon-italic{ + background-position: -27px 1px; +} +.ke-container-qq .ke-icon-italic{ + background-position: -28px 1px; +} +.ke-container-qq .ke-icon-underline{ + background-position: -60px 1px; +} +.ke-container-qq .ke-icon-fontname{ + background-position: -95px 1px; +} +.ke-container-qq .ke-icon-fontsize{ + background-position: -128px 1px; +} +.ke-container-qq .ke-icon-forecolor{ + background-position: -159px 1px; +} +.ke-container-qq .ke-icon-hilitecolor{ + background-position: -190px 1px; +} +.ke-container-qq .ke-icon-plug-align{ + background-position: -223px 1px; +} +.plug-align-justifyleft{ + background-position: -350px 1px; +} +.plug-align-justifycenter{ + background-position: -382px 1px; +} +.plug-align-justifyright{ + background-position: -414px 1px; +} +.plug-order-insertorderedlist{ + background-position: -446px 1px; +} +.plug-order-insertunorderedlist{ + background-position: -477px 1px; +} +.plug-indent-indent{ + background-position: -513px 1px; +} +.plug-indent-outdent{ + background-position: -545px 1px; +} +.ke-container-qq .ke-icon-plug-order{ + background-position: -255px 1px; +} +.ke-container-qq .ke-icon-plug-indent{ + background-position: -287px 1px; +} +.ke-container-qq .ke-icon-link{ + background-position: -319px 1px; +} + +.ke-container-qq .ke-toolbar .ke-outline { + cursor: default; + padding:0px; + border:1px solid #fff; +} +.ke-container-qq .ke-toolbar .ke-on { + border-left:1px solid white; + border-top:1px solid white; + border-right:1px solid gray; + border-bottom:1px solid gray; + background-color: #FFFFFF; +} +.ke-container-qq .ke-toolbar .ke-selected { + border-left:1px solid gray; + border-top:1px solid gray; + border-right:1px solid white; + border-bottom:1px solid white; + background-color: #FFFFFF; +} +.ke-container-qq .ke-toolbar .ke-disabled { + cursor: default; +} + +.ke-colorpicker-qq{ + background:#fff; +} +/* statusbar */ +.ke-container-qq .ke-statusbar { + display:none; +} +/* menu */ +.ke-menu-qq { + border:1px solid #a6a6a6; + position:absolute; + background:#fff; + -moz-box-shadow:2px 2px 4px #DDDDDD; + z-index:999; + left:-400px; + top:-386px; + right:218px; + width:130px; +} +.ke-menu-qq .ke-menu-item { + padding:0px; + background:#fff; +} +.ke-menu-qq .ke-menu-item-on { + border:1px solid #000080;background:#FFEEC2;color:#036; +} +.ke-menu-qq .ke-toolbar .ke-selected { + border:1px solid #9a9afb; +} +.ke-menu-qq .ke-menu-item-left{ + width:auto; +} diff --git a/web/resource/components/tinymce/langs/readme.md b/web/resource/components/tinymce/langs/readme.md new file mode 100644 index 0000000..a52bf03 --- /dev/null +++ b/web/resource/components/tinymce/langs/readme.md @@ -0,0 +1,3 @@ +This is where language files should be placed. + +Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/ diff --git a/web/resource/components/tinymce/plugins/advlist/plugin.min.js b/web/resource/components/tinymce/plugins/advlist/plugin.min.js new file mode 100644 index 0000000..a4db7cc --- /dev/null +++ b/web/resource/components/tinymce/plugins/advlist/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("advlist",function(t){function e(t,e){var n=[];return tinymce.each(e.split(/[ ,]/),function(t){n.push({text:t.replace(/\-/g," ").replace(/\b\w/g,function(t){return t.toUpperCase()}),data:"default"==t?"":t})}),n}function n(e,n){var o,l=t.dom,a=t.selection;o=l.getParent(a.getNode(),"ol,ul"),o&&o.nodeName==e&&n!==!1||t.execCommand("UL"==e?"InsertUnorderedList":"InsertOrderedList"),n=n===!1?i[e]:n,i[e]=n,o=l.getParent(a.getNode(),"ol,ul"),o&&(l.setStyle(o,"listStyleType",n),o.removeAttribute("data-mce-style")),t.focus()}function o(e){var n=t.dom.getStyle(t.dom.getParent(t.selection.getNode(),"ol,ul"),"listStyleType")||"";e.control.items().each(function(t){t.active(t.settings.data===n)})}var l,a,i={};l=e("OL",t.getParam("advlist_number_styles","default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman")),a=e("UL",t.getParam("advlist_bullet_styles","default,circle,disc,square")),t.addButton("numlist",{type:"splitbutton",tooltip:"Numbered list",menu:l,onshow:o,onselect:function(t){n("OL",t.control.settings.data)},onclick:function(){n("OL",!1)}}),t.addButton("bullist",{type:"splitbutton",tooltip:"Bullet list",menu:a,onshow:o,onselect:function(t){n("UL",t.control.settings.data)},onclick:function(){n("UL",!1)}})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/anchor/plugin.min.js b/web/resource/components/tinymce/plugins/anchor/plugin.min.js new file mode 100644 index 0000000..058e686 --- /dev/null +++ b/web/resource/components/tinymce/plugins/anchor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("anchor",function(n){function e(){var e=n.selection.getNode();n.windowManager.open({title:"Anchor",body:{type:"textbox",name:"name",size:40,label:"Name",value:e.name||e.id},onsubmit:function(e){n.execCommand("mceInsertContent",!1,n.dom.createHTML("a",{id:e.data.name}))}})}n.addButton("anchor",{icon:"anchor",tooltip:"Anchor",onclick:e,stateSelector:"a:not([href])"}),n.addMenuItem("anchor",{icon:"anchor",text:"Anchor",context:"insert",onclick:e})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/autolink/plugin.min.js b/web/resource/components/tinymce/plugins/autolink/plugin.min.js new file mode 100644 index 0000000..c49c679 --- /dev/null +++ b/web/resource/components/tinymce/plugins/autolink/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autolink",function(t){function n(t){o(t,-1,"(",!0)}function e(t){o(t,0,"",!0)}function i(t){o(t,-1,"",!1)}function o(t,n,e){function i(t,n){if(0>n&&(n=0),3==t.nodeType){var e=t.data.length;n>e&&(n=e)}return n}function o(t,n){f.setStart(t,i(t,n))}function r(t,n){f.setEnd(t,i(t,n))}var f,d,a,s,c,l,u,g,h;if(f=t.selection.getRng(!0).cloneRange(),f.startOffset<5){if(g=f.endContainer.previousSibling,!g){if(!f.endContainer.firstChild||!f.endContainer.firstChild.nextSibling)return;g=f.endContainer.firstChild.nextSibling}if(h=g.length,o(g,h),r(g,h),f.endOffset<5)return;d=f.endOffset,s=g}else{if(s=f.endContainer,3!=s.nodeType&&s.firstChild){for(;3!=s.nodeType&&s.firstChild;)s=s.firstChild;3==s.nodeType&&(o(s,0),r(s,s.nodeValue.length))}d=1==f.endOffset?2:f.endOffset-1-n}a=d;do o(s,d>=2?d-2:0),r(s,d>=1?d-1:0),d-=1;while(" "!=f.toString()&&""!==f.toString()&&160!=f.toString().charCodeAt(0)&&d-2>=0&&f.toString()!=e);f.toString()==e||160==f.toString().charCodeAt(0)?(o(s,d),r(s,a),d+=1):0===f.startOffset?(o(s,0),r(s,a)):(o(s,d),r(s,a)),l=f.toString(),"."==l.charAt(l.length-1)&&r(s,a-1),l=f.toString(),u=l.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+\-]+@)(.+)$/i),u&&("www."==u[1]?u[1]="http://www.":/@$/.test(u[1])&&!/^mailto:/.test(u[1])&&(u[1]="mailto:"+u[1]),c=t.selection.getBookmark(),t.selection.setRng(f),t.execCommand("createlink",!1,u[1]+u[2]),t.selection.moveToBookmark(c),t.nodeChanged())}var r;return t.on("keydown",function(n){return 13==n.keyCode?i(t):void 0}),tinymce.Env.ie?void t.on("focus",function(){if(!r){r=!0;try{t.execCommand("AutoUrlDetect",!1,!0)}catch(n){}}}):(t.on("keypress",function(e){return 41==e.keyCode?n(t):void 0}),void t.on("keyup",function(n){return 32==n.keyCode?e(t):void 0}))}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/autoresize/plugin.min.js b/web/resource/components/tinymce/plugins/autoresize/plugin.min.js new file mode 100644 index 0000000..fed1d4f --- /dev/null +++ b/web/resource/components/tinymce/plugins/autoresize/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autoresize",function(e){function t(){return e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen()}function i(n){var s,r,g,u,l,m,h,d,f=tinymce.DOM;if(r=e.getDoc()){if(g=r.body,u=r.documentElement,l=o.autoresize_min_height,!g||n&&"setcontent"===n.type&&n.initial||t())return void(g&&u&&(g.style.overflowY="auto",u.style.overflowY="auto"));h=e.dom.getStyle(g,"margin-top",!0),d=e.dom.getStyle(g,"margin-bottom",!0),m=g.offsetHeight+parseInt(h,10)+parseInt(d,10),(isNaN(m)||0>=m)&&(m=tinymce.Env.ie?g.scrollHeight:tinymce.Env.webkit&&0===g.clientHeight?0:g.offsetHeight),m>o.autoresize_min_height&&(l=m),o.autoresize_max_height&&m>o.autoresize_max_height?(l=o.autoresize_max_height,g.style.overflowY="auto",u.style.overflowY="auto"):(g.style.overflowY="hidden",u.style.overflowY="hidden",g.scrollTop=0),l!==a&&(s=l-a,f.setStyle(f.get(e.id+"_ifr"),"height",l+"px"),a=l,tinymce.isWebKit&&0>s&&i(n))}}function n(e,t,o){setTimeout(function(){i({}),e--?n(e,t,o):o&&o()},t)}var o=e.settings,a=0;e.settings.inline||(o.autoresize_min_height=parseInt(e.getParam("autoresize_min_height",e.getElement().offsetHeight),10),o.autoresize_max_height=parseInt(e.getParam("autoresize_max_height",0),10),e.on("init",function(){var t=e.getParam("autoresize_overflow_padding",1);e.dom.setStyles(e.getBody(),{paddingBottom:e.getParam("autoresize_bottom_margin",50),paddingLeft:t,paddingRight:t})}),e.on("nodechange setcontent keyup FullscreenStateChanged",i),e.getParam("autoresize_on_init",!0)&&e.on("init",function(){n(20,100,function(){n(5,1e3)})}),e.addCommand("mceAutoResize",i))}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/autosave/plugin.min.js b/web/resource/components/tinymce/plugins/autosave/plugin.min.js new file mode 100644 index 0000000..bb41975 --- /dev/null +++ b/web/resource/components/tinymce/plugins/autosave/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autosave",function(e){function t(e,t){var n={s:1e3,m:6e4};return e=/^(\d+)([ms]?)$/.exec(""+(e||t)),(e[2]?n[e[2]]:1)*parseInt(e,10)}function n(){var e=parseInt(l.getItem(d+"time"),10)||0;return(new Date).getTime()-e>v.autosave_retention?(a(!1),!1):!0}function a(t){l.removeItem(d+"draft"),l.removeItem(d+"time"),t!==!1&&e.fire("RemoveDraft")}function r(){!c()&&e.isDirty()&&(l.setItem(d+"draft",e.getContent({format:"raw",no_events:!0})),l.setItem(d+"time",(new Date).getTime()),e.fire("StoreDraft"))}function o(){n()&&(e.setContent(l.getItem(d+"draft"),{format:"raw"}),e.fire("RestoreDraft"))}function i(){m||(setInterval(function(){e.removed||r()},v.autosave_interval),m=!0)}function s(){var t=this;t.disabled(!n()),e.on("StoreDraft RestoreDraft RemoveDraft",function(){t.disabled(!n())}),i()}function u(){e.undoManager.beforeChange(),o(),a(),e.undoManager.add()}function f(){var e;return tinymce.each(tinymce.editors,function(t){t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&t.getParam("autosave_ask_before_unload",!0)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))}),e}function c(t){var n=e.settings.forced_root_block;return t=tinymce.trim("undefined"==typeof t?e.getBody().innerHTML:t),""===t||new RegExp("^<"+n+"[^>]*>(( | |[ ]|]*>)+?|)|
$","i").test(t)}var d,m,v=e.settings,l=tinymce.util.LocalStorage;d=v.autosave_prefix||"tinymce-autosave-{path}{query}-{id}-",d=d.replace(/\{path\}/g,document.location.pathname),d=d.replace(/\{query\}/g,document.location.search),d=d.replace(/\{id\}/g,e.id),v.autosave_interval=t(v.autosave_interval,"30s"),v.autosave_retention=t(v.autosave_retention,"20m"),e.addButton("restoredraft",{title:"Restore last draft",onclick:u,onPostRender:s}),e.addMenuItem("restoredraft",{text:"Restore last draft",onclick:u,onPostRender:s,context:"file"}),e.settings.autosave_restore_when_empty!==!1&&(e.on("init",function(){n()&&c()&&o()}),e.on("saveContent",function(){a()})),window.onbeforeunload=f,this.hasDraft=n,this.storeDraft=r,this.restoreDraft=o,this.removeDraft=a,this.isEmpty=c}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/bbcode/plugin.min.js b/web/resource/components/tinymce/plugins/bbcode/plugin.min.js new file mode 100644 index 0000000..78c37cd --- /dev/null +++ b/web/resource/components/tinymce/plugins/bbcode/plugin.min.js @@ -0,0 +1 @@ +!function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(o){var e=this,t=o.getParam("bbcode_dialect","punbb").toLowerCase();o.on("beforeSetContent",function(o){o.content=e["_"+t+"_bbcode2html"](o.content)}),o.on("postProcess",function(o){o.set&&(o.content=e["_"+t+"_bbcode2html"](o.content)),o.get&&(o.content=e["_"+t+"_html2bbcode"](o.content))})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://www.tinymce.com",infourl:"http://www.tinymce.com/wiki.php/Plugin:bbcode"}},_punbb_html2bbcode:function(o){function e(e,t){o=o.replace(e,t)}return o=tinymce.trim(o),e(/(.*?)<\/a>/gi,"[url=$1]$2[/url]"),e(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),e(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),e(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),e(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),e(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),e(/(.*?)<\/font>/gi,"[color=$1]$2[/color]"),e(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),e(/(.*?)<\/font>/gi,"$1"),e(//gi,"[img]$1[/img]"),e(/(.*?)<\/span>/gi,"[code]$1[/code]"),e(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),e(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),e(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),e(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),e(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),e(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),e(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),e(/<\/(strong|b)>/gi,"[/b]"),e(/<(strong|b)>/gi,"[b]"),e(/<\/(em|i)>/gi,"[/i]"),e(/<(em|i)>/gi,"[i]"),e(/<\/u>/gi,"[/u]"),e(/(.*?)<\/span>/gi,"[u]$1[/u]"),e(//gi,"[u]"),e(/]*>/gi,"[quote]"),e(/<\/blockquote>/gi,"[/quote]"),e(/
/gi,"\n"),e(//gi,"\n"),e(/
/gi,"\n"),e(/

/gi,""),e(/<\/p>/gi,"\n"),e(/ |\u00a0/gi," "),e(/"/gi,'"'),e(/</gi,"<"),e(/>/gi,">"),e(/&/gi,"&"),o},_punbb_bbcode2html:function(o){function e(e,t){o=o.replace(e,t)}return o=tinymce.trim(o),e(/\n/gi,"
"),e(/\[b\]/gi,""),e(/\[\/b\]/gi,""),e(/\[i\]/gi,""),e(/\[\/i\]/gi,""),e(/\[u\]/gi,""),e(/\[\/u\]/gi,""),e(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2'),e(/\[url\](.*?)\[\/url\]/gi,'$1'),e(/\[img\](.*?)\[\/img\]/gi,''),e(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),e(/\[code\](.*?)\[\/code\]/gi,'$1 '),e(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),o}}),tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)}(); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/charmap/plugin.min.js b/web/resource/components/tinymce/plugins/charmap/plugin.min.js new file mode 100644 index 0000000..46fce44 --- /dev/null +++ b/web/resource/components/tinymce/plugins/charmap/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("charmap",function(e){function a(){function a(e){for(;e;){if("TD"==e.nodeName)return e;e=e.parentNode}}var t,r,o,n;t='';var l=25;for(o=0;10>o;o++){for(t+="",r=0;l>r;r++){var s=i[o*l+r];t+='"}t+=""}t+="";var c={type:"container",html:t,onclick:function(a){var i=a.target;"TD"==i.tagName&&(i=i.firstChild),"DIV"==i.tagName&&(e.execCommand("mceInsertContent",!1,i.firstChild.data),a.ctrlKey||n.close())},onmouseover:function(e){var i=a(e.target);i&&n.find("#preview").text(i.firstChild.firstChild.data)}};n=e.windowManager.open({title:"Special character",spacing:10,padding:10,items:[c,{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:100,minHeight:80}],buttons:[{text:"Close",onclick:function(){n.close()}}]})}var i=[["160","no-break space"],["38","ampersand"],["34","quotation mark"],["162","cent sign"],["8364","euro sign"],["163","pound sign"],["165","yen sign"],["169","copyright sign"],["174","registered sign"],["8482","trade mark sign"],["8240","per mille sign"],["181","micro sign"],["183","middle dot"],["8226","bullet"],["8230","three dot leader"],["8242","minutes / feet"],["8243","seconds / inches"],["167","section sign"],["182","paragraph sign"],["223","sharp s / ess-zed"],["8249","single left-pointing angle quotation mark"],["8250","single right-pointing angle quotation mark"],["171","left pointing guillemet"],["187","right pointing guillemet"],["8216","left single quotation mark"],["8217","right single quotation mark"],["8220","left double quotation mark"],["8221","right double quotation mark"],["8218","single low-9 quotation mark"],["8222","double low-9 quotation mark"],["60","less-than sign"],["62","greater-than sign"],["8804","less-than or equal to"],["8805","greater-than or equal to"],["8211","en dash"],["8212","em dash"],["175","macron"],["8254","overline"],["164","currency sign"],["166","broken bar"],["168","diaeresis"],["161","inverted exclamation mark"],["191","turned question mark"],["710","circumflex accent"],["732","small tilde"],["176","degree sign"],["8722","minus sign"],["177","plus-minus sign"],["247","division sign"],["8260","fraction slash"],["215","multiplication sign"],["185","superscript one"],["178","superscript two"],["179","superscript three"],["188","fraction one quarter"],["189","fraction one half"],["190","fraction three quarters"],["402","function / florin"],["8747","integral"],["8721","n-ary sumation"],["8734","infinity"],["8730","square root"],["8764","similar to"],["8773","approximately equal to"],["8776","almost equal to"],["8800","not equal to"],["8801","identical to"],["8712","element of"],["8713","not an element of"],["8715","contains as member"],["8719","n-ary product"],["8743","logical and"],["8744","logical or"],["172","not sign"],["8745","intersection"],["8746","union"],["8706","partial differential"],["8704","for all"],["8707","there exists"],["8709","diameter"],["8711","backward difference"],["8727","asterisk operator"],["8733","proportional to"],["8736","angle"],["180","acute accent"],["184","cedilla"],["170","feminine ordinal indicator"],["186","masculine ordinal indicator"],["8224","dagger"],["8225","double dagger"],["192","A - grave"],["193","A - acute"],["194","A - circumflex"],["195","A - tilde"],["196","A - diaeresis"],["197","A - ring above"],["198","ligature AE"],["199","C - cedilla"],["200","E - grave"],["201","E - acute"],["202","E - circumflex"],["203","E - diaeresis"],["204","I - grave"],["205","I - acute"],["206","I - circumflex"],["207","I - diaeresis"],["208","ETH"],["209","N - tilde"],["210","O - grave"],["211","O - acute"],["212","O - circumflex"],["213","O - tilde"],["214","O - diaeresis"],["216","O - slash"],["338","ligature OE"],["352","S - caron"],["217","U - grave"],["218","U - acute"],["219","U - circumflex"],["220","U - diaeresis"],["221","Y - acute"],["376","Y - diaeresis"],["222","THORN"],["224","a - grave"],["225","a - acute"],["226","a - circumflex"],["227","a - tilde"],["228","a - diaeresis"],["229","a - ring above"],["230","ligature ae"],["231","c - cedilla"],["232","e - grave"],["233","e - acute"],["234","e - circumflex"],["235","e - diaeresis"],["236","i - grave"],["237","i - acute"],["238","i - circumflex"],["239","i - diaeresis"],["240","eth"],["241","n - tilde"],["242","o - grave"],["243","o - acute"],["244","o - circumflex"],["245","o - tilde"],["246","o - diaeresis"],["248","o slash"],["339","ligature oe"],["353","s - caron"],["249","u - grave"],["250","u - acute"],["251","u - circumflex"],["252","u - diaeresis"],["253","y - acute"],["254","thorn"],["255","y - diaeresis"],["913","Alpha"],["914","Beta"],["915","Gamma"],["916","Delta"],["917","Epsilon"],["918","Zeta"],["919","Eta"],["920","Theta"],["921","Iota"],["922","Kappa"],["923","Lambda"],["924","Mu"],["925","Nu"],["926","Xi"],["927","Omicron"],["928","Pi"],["929","Rho"],["931","Sigma"],["932","Tau"],["933","Upsilon"],["934","Phi"],["935","Chi"],["936","Psi"],["937","Omega"],["945","alpha"],["946","beta"],["947","gamma"],["948","delta"],["949","epsilon"],["950","zeta"],["951","eta"],["952","theta"],["953","iota"],["954","kappa"],["955","lambda"],["956","mu"],["957","nu"],["958","xi"],["959","omicron"],["960","pi"],["961","rho"],["962","final sigma"],["963","sigma"],["964","tau"],["965","upsilon"],["966","phi"],["967","chi"],["968","psi"],["969","omega"],["8501","alef symbol"],["982","pi symbol"],["8476","real part symbol"],["978","upsilon - hook symbol"],["8472","Weierstrass p"],["8465","imaginary part"],["8592","leftwards arrow"],["8593","upwards arrow"],["8594","rightwards arrow"],["8595","downwards arrow"],["8596","left right arrow"],["8629","carriage return"],["8656","leftwards double arrow"],["8657","upwards double arrow"],["8658","rightwards double arrow"],["8659","downwards double arrow"],["8660","left right double arrow"],["8756","therefore"],["8834","subset of"],["8835","superset of"],["8836","not a subset of"],["8838","subset of or equal to"],["8839","superset of or equal to"],["8853","circled plus"],["8855","circled times"],["8869","perpendicular"],["8901","dot operator"],["8968","left ceiling"],["8969","right ceiling"],["8970","left floor"],["8971","right floor"],["9001","left-pointing angle bracket"],["9002","right-pointing angle bracket"],["9674","lozenge"],["9824","black spade suit"],["9827","black club suit"],["9829","black heart suit"],["9830","black diamond suit"],["8194","en space"],["8195","em space"],["8201","thin space"],["8204","zero width non-joiner"],["8205","zero width joiner"],["8206","left-to-right mark"],["8207","right-to-left mark"],["173","soft hyphen"]];e.addButton("charmap",{icon:"charmap",tooltip:"Special character",onclick:a}),e.addMenuItem("charmap",{icon:"charmap",text:"Special character",onclick:a,context:"insert"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/code/plugin.min.js b/web/resource/components/tinymce/plugins/code/plugin.min.js new file mode 100644 index 0000000..9e7e898 --- /dev/null +++ b/web/resource/components/tinymce/plugins/code/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("code",function(e){function o(){e.windowManager.open({title:"Source code",body:{type:"textbox",name:"code",multiline:!0,minWidth:e.getParam("code_dialog_width",600),minHeight:e.getParam("code_dialog_height",Math.min(tinymce.DOM.getViewPort().h-200,500)),value:e.getContent({source_view:!0}),spellcheck:!1,style:"direction: ltr; text-align: left"},onSubmit:function(o){e.focus(),e.undoManager.transact(function(){e.setContent(o.data.code)}),e.selection.setCursorLocation(),e.nodeChanged()}})}e.addCommand("mceCodeEditor",o),e.addButton("code",{icon:"code",tooltip:"Source code",onclick:o}),e.addMenuItem("code",{icon:"code",text:"Source code",context:"tools",onclick:o})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/contextmenu/plugin.min.js b/web/resource/components/tinymce/plugins/contextmenu/plugin.min.js new file mode 100644 index 0000000..66d034d --- /dev/null +++ b/web/resource/components/tinymce/plugins/contextmenu/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("contextmenu",function(e){var n,t=e.settings.contextmenu_never_use_native;e.on("contextmenu",function(i){var o;if(!i.ctrlKey||t){if(i.preventDefault(),o=e.settings.contextmenu||"link image multiimage inserttable | cell row column deletetable",n)n.show();else{var c=[];tinymce.each(o.split(/[ ,]/),function(n){var t=e.menuItems[n];"|"==n&&(t={text:n}),t&&(t.shortcut="",c.push(t))});for(var a=0;a'}),t+=""}),t+=""}var i=[["cool","cry","embarassed","foot-in-mouth"],["frown","innocent","kiss","laughing"],["money-mouth","sealed","smile","surprised"],["tongue-out","undecided","wink","yell"]];t.addButton("emoticons",{type:"panelbutton",panel:{role:"application",autohide:!0,html:a,onclick:function(e){var a=t.dom.getParent(e.target,"a");a&&(t.insertContent(''+a.getAttribute('),this.hide())}},tooltip:"Emoticons"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/example/plugin.min.js b/web/resource/components/tinymce/plugins/example/plugin.min.js new file mode 100644 index 0000000..00a262e --- /dev/null +++ b/web/resource/components/tinymce/plugins/example/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("example",function(t,e){t.addButton("example",{text:"My button",icon:!1,onclick:function(){t.windowManager.open({title:"Example plugin",body:[{type:"textbox",name:"title",label:"Title"}],onsubmit:function(e){t.insertContent("Title: "+e.data.title)}})}}),t.addMenuItem("example",{text:"Example plugin",context:"tools",onclick:function(){t.windowManager.open({title:"TinyMCE site",url:e+"/dialog.html",width:600,height:400,buttons:[{text:"Insert",onclick:function(){var e=t.windowManager.getWindows()[0];t.insertContent(e.getContentWindow().document.getElementById("content").value),e.close()}},{text:"Close",onclick:"close"}]})}})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/example_dependency/plugin.min.js b/web/resource/components/tinymce/plugins/example_dependency/plugin.min.js new file mode 100644 index 0000000..e61bf47 --- /dev/null +++ b/web/resource/components/tinymce/plugins/example_dependency/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("example_dependency",function(){},["example"]); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/fullpage/plugin.min.js b/web/resource/components/tinymce/plugins/fullpage/plugin.min.js new file mode 100644 index 0000000..1da17c9 --- /dev/null +++ b/web/resource/components/tinymce/plugins/fullpage/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("fullpage",function(e){function t(){var t=n();e.windowManager.open({title:"Document properties",data:t,defaults:{type:"textbox",size:40},body:[{name:"title",label:"Title"},{name:"keywords",label:"Keywords"},{name:"description",label:"Description"},{name:"robots",label:"Robots"},{name:"author",label:"Author"},{name:"docencoding",label:"Encoding"}],onSubmit:function(e){l(tinymce.extend(t,e.data))}})}function n(){function t(e,t){var n=e.attr(t);return n||""}var n,l,a=i(),r={};return r.fontface=e.getParam("fullpage_default_fontface",""),r.fontsize=e.getParam("fullpage_default_fontsize",""),n=a.firstChild,7==n.type&&(r.xml_pi=!0,l=/encoding="([^"]+)"/.exec(n.value),l&&(r.docencoding=l[1])),n=a.getAll("#doctype")[0],n&&(r.doctype=""),n=a.getAll("title")[0],n&&n.firstChild&&(r.title=n.firstChild.value),s(a.getAll("meta"),function(e){var t,n=e.attr("name"),l=e.attr("http-equiv");n?r[n.toLowerCase()]=e.attr("content"):"Content-Type"==l&&(t=/charset\s*=\s*(.*)\s*/gi.exec(e.attr("content")),t&&(r.docencoding=t[1]))}),n=a.getAll("html")[0],n&&(r.langcode=t(n,"lang")||t(n,"xml:lang")),r.stylesheets=[],tinymce.each(a.getAll("link"),function(e){"stylesheet"==e.attr("rel")&&r.stylesheets.push(e.attr("href"))}),n=a.getAll("body")[0],n&&(r.langdir=t(n,"dir"),r.style=t(n,"style"),r.visited_color=t(n,"vlink"),r.link_color=t(n,"link"),r.active_color=t(n,"alink")),r}function l(t){function n(e,t,n){e.attr(t,n?n:void 0)}function l(e){r.firstChild?r.insert(e,r.firstChild):r.append(e)}var a,r,o,c,u,f=e.dom;a=i(),r=a.getAll("head")[0],r||(c=a.getAll("html")[0],r=new m("head",1),c.firstChild?c.insert(r,c.firstChild,!0):c.append(r)),c=a.firstChild,t.xml_pi?(u='version="1.0"',t.docencoding&&(u+=' encoding="'+t.docencoding+'"'),7!=c.type&&(c=new m("xml",7),a.insert(c,a.firstChild,!0)),c.value=u):c&&7==c.type&&c.remove(),c=a.getAll("#doctype")[0],t.doctype?(c||(c=new m("#doctype",10),t.xml_pi?a.insert(c,a.firstChild):l(c)),c.value=t.doctype.substring(9,t.doctype.length-1)):c&&c.remove(),c=null,s(a.getAll("meta"),function(e){"Content-Type"==e.attr("http-equiv")&&(c=e)}),t.docencoding?(c||(c=new m("meta",1),c.attr("http-equiv","Content-Type"),c.shortEnded=!0,l(c)),c.attr("content","text/html; charset="+t.docencoding)):c.remove(),c=a.getAll("title")[0],t.title?(c?c.empty():(c=new m("title",1),l(c)),c.append(new m("#text",3)).value=t.title):c&&c.remove(),s("keywords,description,author,copyright,robots".split(","),function(e){var n,i,r=a.getAll("meta"),o=t[e];for(n=0;n"))}function i(){return new tinymce.html.DomParser({validate:!1,root_name:"#document"}).parse(d)}function a(t){function n(e){return e.replace(/<\/?[A-Z]+/g,function(e){return e.toLowerCase()})}var l,a,o,m,u=t.content,f="",g=e.dom;if(!t.selection&&!("raw"==t.format&&d||t.source_view&&e.getParam("fullpage_hide_in_source_view"))){u=u.replace(/<(\/?)BODY/gi,"<$1body"),l=u.indexOf("",l),d=n(u.substring(0,l+1)),a=u.indexOf("\n"),o=i(),s(o.getAll("style"),function(e){e.firstChild&&(f+=e.firstChild.value)}),m=o.getAll("body")[0],m&&g.setAttribs(e.getBody(),{style:m.attr("style")||"",dir:m.attr("dir")||"",vLink:m.attr("vlink")||"",link:m.attr("link")||"",aLink:m.attr("alink")||""}),g.remove("fullpage_styles");var y=e.getDoc().getElementsByTagName("head")[0];f&&(g.add(y,"style",{id:"fullpage_styles"},f),m=g.get("fullpage_styles"),m.styleSheet&&(m.styleSheet.cssText=f));var h={};tinymce.each(y.getElementsByTagName("link"),function(e){"stylesheet"==e.rel&&e.getAttribute("data-mce-fullpage")&&(h[e.href]=e)}),tinymce.each(o.getAll("link"),function(e){var t=e.attr("href");h[t]||"stylesheet"!=e.attr("rel")||g.add(y,"link",{rel:"stylesheet",text:"text/css",href:t,"data-mce-fullpage":"1"}),delete h[t]}),tinymce.each(h,function(e){e.parentNode.removeChild(e)})}}function r(){var t,n="",l="";return e.getParam("fullpage_default_xml_pi")&&(n+='\n'),n+=e.getParam("fullpage_default_doctype",""),n+="\n\n\n",(t=e.getParam("fullpage_default_title"))&&(n+=""+t+"\n"),(t=e.getParam("fullpage_default_encoding"))&&(n+='\n'),(t=e.getParam("fullpage_default_font_family"))&&(l+="font-family: "+t+";"),(t=e.getParam("fullpage_default_font_size"))&&(l+="font-size: "+t+";"),(t=e.getParam("fullpage_default_text_color"))&&(l+="color: "+t+";"),n+="\n\n"}function o(t){t.selection||t.source_view&&e.getParam("fullpage_hide_in_source_view")||(t.content=tinymce.trim(d)+"\n"+tinymce.trim(t.content)+"\n"+tinymce.trim(c))}var d,c,s=tinymce.each,m=tinymce.html.Node;e.addCommand("mceFullPageProperties",t),e.addButton("fullpage",{title:"Document properties",cmd:"mceFullPageProperties"}),e.addMenuItem("fullpage",{text:"Document properties",cmd:"mceFullPageProperties",context:"file"}),e.on("BeforeSetContent",a),e.on("GetContent",o)}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/fullscreen/plugin.min.js b/web/resource/components/tinymce/plugins/fullscreen/plugin.min.js new file mode 100644 index 0000000..1bb1940 --- /dev/null +++ b/web/resource/components/tinymce/plugins/fullscreen/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("fullscreen",function(e){function t(){var e,t,n=window,i=document,l=i.body;return l.offsetWidth&&(e=l.offsetWidth,t=l.offsetHeight),n.innerWidth&&n.innerHeight&&(e=n.innerWidth,t=n.innerHeight),{w:e,h:t}}function n(){function n(){d.setStyle(a,"height",t().h-(h.clientHeight-a.clientHeight))}var u,h,a,f,m=document.body,g=document.documentElement;s=!s,h=e.getContainer(),u=h.style,a=e.getContentAreaContainer().firstChild,f=a.style,s?(i=f.width,l=f.height,f.width=f.height="100%",c=u.width,o=u.height,u.width=u.height="",d.addClass(m,"mce-fullscreen"),d.addClass(g,"mce-fullscreen"),d.addClass(h,"mce-fullscreen"),d.bind(window,"resize",n),n(),r=n):(f.width=i,f.height=l,c&&(u.width=c),o&&(u.height=o),d.removeClass(m,"mce-fullscreen"),d.removeClass(g,"mce-fullscreen"),d.removeClass(h,"mce-fullscreen"),d.unbind(window,"resize",r)),e.fire("FullscreenStateChanged",{state:s})}var i,l,r,c,o,s=!1,d=tinymce.DOM;return e.settings.inline?void 0:(e.on("init",function(){e.addShortcut("Ctrl+Alt+F","",n)}),e.on("remove",function(){r&&d.unbind(window,"resize",r)}),e.addCommand("mceFullScreen",n),e.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Alt+F",selectable:!0,onClick:n,onPostRender:function(){var t=this;e.on("FullscreenStateChanged",function(e){t.active(e.state)})},context:"view"}),e.addButton("fullscreen",{tooltip:"Fullscreen",shortcut:"Ctrl+Alt+F",onClick:n,onPostRender:function(){var t=this;e.on("FullscreenStateChanged",function(e){t.active(e.state)})}}),{isFullscreen:function(){return s}})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/hr/plugin.min.js b/web/resource/components/tinymce/plugins/hr/plugin.min.js new file mode 100644 index 0000000..e5ff6f3 --- /dev/null +++ b/web/resource/components/tinymce/plugins/hr/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("hr",function(n){n.addCommand("InsertHorizontalRule",function(){n.execCommand("mceInsertContent",!1,"


")}),n.addButton("hr",{icon:"hr",tooltip:"Horizontal line",cmd:"InsertHorizontalRule"}),n.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/image/plugin.min.js b/web/resource/components/tinymce/plugins/image/plugin.min.js new file mode 100644 index 0000000..7c6b3b6 --- /dev/null +++ b/web/resource/components/tinymce/plugins/image/plugin.min.js @@ -0,0 +1,48 @@ +tinymce.PluginManager.add('image', function(editor) { + function handleImageDialog() { + var dom = editor.dom; + var imgElm = editor.selection.getNode(); + require(['util'], function(u){ + var v = ''; + if (imgElm && imgElm.tagName.toLowerCase() == 'img') { + v = imgElm.src; + } + u.image(v, function(val){ + data = { + src: val.url, + alt: val.filename, + title: val.filename + }; + + if (!data["class"]) { + delete data["class"]; + } + + if (!imgElm || imgElm.tagName.toLowerCase() != 'img') { + data.id = '__mcenew'; + editor.focus(); + editor.selection.setContent(dom.createHTML('img', data)); + imgElm = dom.get('__mcenew'); + dom.setAttrib(imgElm, 'id', null); + } else { + dom.setAttribs(imgElm, data); + } + },'', {direct: true, multi : false} ); + }); + } + + editor.addButton('image', { + icon: 'image', + tooltip: 'Insert/edit image', + onclick: handleImageDialog, + stateSelector: 'img:not([data-mce-object],[data-mce-placeholder])' + }); + + editor.addMenuItem('image', { + icon: 'image', + text: 'Insert image', + onclick: handleImageDialog, + context: 'insert', + prependToContext: true + }); +}); diff --git a/web/resource/components/tinymce/plugins/importcss/plugin.min.js b/web/resource/components/tinymce/plugins/importcss/plugin.min.js new file mode 100644 index 0000000..5dd1d44 --- /dev/null +++ b/web/resource/components/tinymce/plugins/importcss/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("importcss",function(t){function e(t){return"string"==typeof t?function(e){return-1!==e.indexOf(t)}:t instanceof RegExp?function(e){return t.test(e)}:t}function n(e,n){function i(t,e){var c,o=t.href;if(o&&n(o,e)){s(t.imports,function(t){i(t,!0)});try{c=t.cssRules||t.rules}catch(a){}s(c,function(t){t.styleSheet?i(t.styleSheet,!0):t.selectorText&&s(t.selectorText.split(","),function(t){r.push(tinymce.trim(t))})})}}var r=[],c={};s(t.contentCSS,function(t){c[t]=!0}),n||(n=function(t,e){return e||c[t]});try{s(e.styleSheets,function(t){i(t)})}catch(o){}return r}function i(e){var n,i=/^(?:([a-z0-9\-_]+))?(\.[a-z0-9_\-\.]+)$/i.exec(e);if(i){var r=i[1],s=i[2].substr(1).split(".").join(" "),c=tinymce.makeMap("a,img");return i[1]?(n={title:e},t.schema.getTextBlockElements()[r]?n.block=r:t.schema.getBlockElements()[r]||c[r.toLowerCase()]?n.selector=r:n.inline=r):i[2]&&(n={inline:"span",title:e.substr(1),classes:s}),t.settings.importcss_merge_classes!==!1?n.classes=s:n.attributes={"class":s},n}}var r=this,s=tinymce.each;t.on("renderFormatsMenu",function(c){var o=t.settings,a={},l=o.importcss_selector_converter||i,f=e(o.importcss_selector_filter),m=c.control;t.settings.importcss_append||m.items().remove();var u=[];tinymce.each(o.importcss_groups,function(t){t=tinymce.extend({},t),t.filter=e(t.filter),u.push(t)}),s(n(c.doc||t.getDoc(),e(o.importcss_file_filter)),function(e){if(-1===e.indexOf(".mce-")&&!a[e]&&(!f||f(e))){var n,i=l.call(r,e);if(i){var s=i.name||tinymce.DOM.uniqueId();if(u)for(var c=0;c'+n+"";var i=e.dom.getParent(e.selection.getStart(),"time");if(i)return void e.dom.setOuterHTML(i,n)}e.insertContent(n)}var n,r,i="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),d="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),c="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),m="January February March April May June July August September October November December".split(" "),u=[];e.addCommand("mceInsertDate",function(){a(e.getParam("insertdatetime_dateformat",e.translate("%Y-%m-%d")))}),e.addCommand("mceInsertTime",function(){a(e.getParam("insertdatetime_timeformat",e.translate("%H:%M:%S")))}),e.addButton("insertdatetime",{type:"splitbutton",title:"Insert date/time",onclick:function(){a(n||r)},menu:u}),tinymce.each(e.settings.insertdatetime_formats||["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"],function(e){r||(r=e),u.push({text:t(e),onclick:function(){n=e,a(e)}})}),e.addMenuItem("insertdatetime",{icon:"date",text:"Insert date/time",menu:u,context:"insert"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/layer/plugin.min.js b/web/resource/components/tinymce/plugins/layer/plugin.min.js new file mode 100644 index 0000000..f100292 --- /dev/null +++ b/web/resource/components/tinymce/plugins/layer/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("layer",function(e){function t(e){do if(e.className&&-1!=e.className.indexOf("mceItemLayer"))return e;while(e=e.parentNode)}function o(t){var o=e.dom;tinymce.each(o.select("div,p",t),function(e){/^(absolute|relative|fixed)$/i.test(e.style.position)&&(e.hasVisual?o.addClass(e,"mceItemVisualAid"):o.removeClass(e,"mceItemVisualAid"),o.addClass(e,"mceItemLayer"))})}function d(o){var d,n,a=[],i=t(e.selection.getNode()),s=-1,l=-1;for(n=[],tinymce.walk(e.getBody(),function(e){1==e.nodeType&&/^(absolute|relative|static)$/i.test(e.style.position)&&n.push(e)},"childNodes"),d=0;ds&&n[d]==i&&(s=d);if(0>o){for(d=0;d-1?(n[s].style.zIndex=a[l],n[l].style.zIndex=a[s]):a[s]>0&&(n[s].style.zIndex=a[s]-1)}else{for(d=0;da[s]){l=d;break}l>-1?(n[s].style.zIndex=a[l],n[l].style.zIndex=a[s]):n[s].style.zIndex=a[s]+1}e.execCommand("mceRepaint")}function n(){var t=e.dom,o=t.getPos(t.getParent(e.selection.getNode(),"*")),d=e.getBody();e.dom.add(d,"div",{style:{position:"absolute",left:o.x,top:o.y>20?o.y:20,width:100,height:100},"class":"mceItemVisualAid mceItemLayer"},e.selection.getContent()||e.getLang("layer.content")),tinymce.Env.ie&&t.setHTML(d,d.innerHTML)}function a(){var o=t(e.selection.getNode());o||(o=e.dom.getParent(e.selection.getNode(),"DIV,P,IMG")),o&&("absolute"==o.style.position.toLowerCase()?(e.dom.setStyles(o,{position:"",left:"",top:"",width:"",height:""}),e.dom.removeClass(o,"mceItemVisualAid"),e.dom.removeClass(o,"mceItemLayer")):(o.style.left||(o.style.left="20px"),o.style.top||(o.style.top="20px"),o.style.width||(o.style.width=o.width?o.width+"px":"100px"),o.style.height||(o.style.height=o.height?o.height+"px":"100px"),o.style.position="absolute",e.dom.setAttrib(o,"data-mce-style",""),e.addVisual(e.getBody())),e.execCommand("mceRepaint"),e.nodeChanged())}e.addCommand("mceInsertLayer",n),e.addCommand("mceMoveForward",function(){d(1)}),e.addCommand("mceMoveBackward",function(){d(-1)}),e.addCommand("mceMakeAbsolute",function(){a()}),e.addButton("moveforward",{title:"layer.forward_desc",cmd:"mceMoveForward"}),e.addButton("movebackward",{title:"layer.backward_desc",cmd:"mceMoveBackward"}),e.addButton("absolute",{title:"layer.absolute_desc",cmd:"mceMakeAbsolute"}),e.addButton("insertlayer",{title:"layer.insertlayer_desc",cmd:"mceInsertLayer"}),e.on("init",function(){tinymce.Env.ie&&e.getDoc().execCommand("2D-Position",!1,!0)}),e.on("mouseup",function(o){var d=t(o.target);d&&e.dom.setAttrib(d,"data-mce-style","")}),e.on("mousedown",function(o){var d,n=o.target,a=e.getDoc();tinymce.Env.gecko&&(t(n)?"on"!==a.designMode&&(a.designMode="on",n=a.body,d=n.parentNode,d.removeChild(n),d.appendChild(n)):"on"==a.designMode&&(a.designMode="off"))}),e.on("NodeChange",o)}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/legacyoutput/plugin.min.js b/web/resource/components/tinymce/plugins/legacyoutput/plugin.min.js new file mode 100644 index 0000000..f77d8e8 --- /dev/null +++ b/web/resource/components/tinymce/plugins/legacyoutput/plugin.min.js @@ -0,0 +1 @@ +!function(e){e.on("AddEditor",function(e){e.editor.settings.inline_styles=!1}),e.PluginManager.add("legacyoutput",function(t){t.on("init",function(){var i="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img",n=e.explode(t.settings.font_size_style_values),l=t.schema;t.formatter.register({alignleft:{selector:i,attributes:{align:"left"}},aligncenter:{selector:i,attributes:{align:"center"}},alignright:{selector:i,attributes:{align:"right"}},alignjustify:{selector:i,attributes:{align:"justify"}},bold:[{inline:"b",remove:"all"},{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}}],italic:[{inline:"i",remove:"all"},{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}}],underline:[{inline:"u",remove:"all"},{inline:"span",styles:{textDecoration:"underline"},exact:!0}],strikethrough:[{inline:"strike",remove:"all"},{inline:"span",styles:{textDecoration:"line-through"},exact:!0}],fontname:{inline:"font",attributes:{face:"%value"}},fontsize:{inline:"font",attributes:{size:function(t){return e.inArray(n,t.value)+1}}},forecolor:{inline:"font",attributes:{color:"%value"}},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"}}}),e.each("b,i,u,strike".split(","),function(e){l.addValidElements(e+"[*]")}),l.getElementRule("font")||l.addValidElements("font[face|size|color|style]"),e.each(i.split(","),function(e){var t=l.getElementRule(e);t&&(t.attributes.align||(t.attributes.align={},t.attributesOrder.push("align")))})})})}(tinymce); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/link/plugin.min.js b/web/resource/components/tinymce/plugins/link/plugin.min.js new file mode 100644 index 0000000..75d5c6f --- /dev/null +++ b/web/resource/components/tinymce/plugins/link/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("link",function(t){function e(e){return function(){var n=t.settings.link_list;"string"==typeof n?tinymce.util.XHR.send({url:n,success:function(t){e(tinymce.util.JSON.parse(t))}}):"function"==typeof n?n(e):e(n)}}function n(e){function n(t){var e=d.find("#text");(!e.value()||t.lastControl&&e.value()==t.lastControl.text())&&e.value(t.control.text()),d.find("#href").value(t.control.value())}function l(){function n(e,l){return l=l||[],tinymce.each(e,function(e){var i={text:e.text||e.title};e.menu?i.menu=n(e.menu):i.value=t.convertURL(e.value||e.url,"href"),l.push(i)}),l}return n(e,[{text:"None",value:""}])}function i(e){return tinymce.each(e,function(e){e.textStyle=function(){return t.formatter.getCssText({inline:"a",classes:[e.value]})}}),e}function a(e,n,l){var i,a=[];return tinymce.each(t.settings[e]||l,function(t){var e={text:t.text||t.title,value:t.value};a.push(e),(b[n]===t.value||!i&&t.selected)&&(i=e)}),i&&!b[n]&&(b[n]=i.value,i.selected=!0),a}function r(e){var l=[];return tinymce.each(t.dom.select("a:not([href])"),function(t){var n=t.name||t.id;n&&l.push({text:n,value:"#"+n,selected:-1!=e.indexOf("#"+n)})}),l.length?(l.unshift({text:"None",value:""}),{name:"anchor",type:"listbox",label:"Anchors",values:l,onselect:n}):void 0}function o(){h&&h.value(t.convertURL(this.value(),"href")),!f&&0===b.text.length&&x&&this.parent().parent().find("#text")[0].value(this.value())}function s(t){var e=k.getContent();if(/]+>[^<]+<\/a>$/.test(e)||-1==e.indexOf("href=")))return!1;if(t){var n,l=t.childNodes;if(0===l.length)return!1;for(n=l.length-1;n>=0;n--)if(3!=l[n].nodeType)return!1}return!0}var u,c,f,d,x,v,h,g,m,p,y,b={},k=t.selection,w=t.dom;u=k.getNode(),c=w.getParent(u,"a[href]"),x=s(),b.text=f=c?c.innerText||c.textContent:k.getContent({format:"text"}),b.href=c?w.getAttrib(c,"href"):"",b.target=c?w.getAttrib(c,"target"):t.settings.default_link_target||null,b.rel=c?w.getAttrib(c,"rel"):null,b["class"]=c?w.getAttrib(c,"class"):null,b.title=c?w.getAttrib(c,"title"):"",x&&(v={name:"text",type:"textbox",size:40,label:"Text to display",onchange:function(){b.text=this.value()}}),e&&(h={type:"listbox",label:"Link list",values:l(),onselect:n,value:t.convertURL(b.href,"href"),onPostRender:function(){h=this}}),t.settings.target_list!==!1&&(m={name:"target",type:"listbox",label:"Target",values:a("target_list","target",[{text:"None",value:""},{text:"New window",value:"_blank"}])}),t.settings.rel_list&&(g={name:"rel",type:"listbox",label:"Rel",values:a("rel_list","rel",[{text:"None",value:""}])}),t.settings.link_class_list&&(p={name:"class",type:"listbox",label:"Class",values:i(a("link_class_list","class"))}),t.settings.link_title!==!1&&(y={name:"title",type:"textbox",label:"Title",value:b.title}),d=t.windowManager.open({title:"Insert link",data:b,body:[{name:"href",type:"filepicker",filetype:"file",size:40,autofocus:!0,label:"Url",onchange:o,onkeyup:o},v,y,r(b.href),h,g,m,p],onSubmit:function(e){function n(e,n){var l=t.selection.getRng();window.setTimeout(function(){t.windowManager.confirm(e,function(e){t.selection.setRng(l),n(e)})},0)}function l(){var e={href:i,target:b.target?b.target:null,rel:b.rel?b.rel:null,"class":b["class"]?b["class"]:null,title:b.title?b.title:null};c?(t.focus(),x&&b.text!=f&&("innerText"in c?c.innerText=b.text:c.textContent=b.text),w.setAttribs(c,e),k.select(c),t.undoManager.add()):x?t.insertContent(w.createHTML("a",e,w.encode(b.text))):t.execCommand("mceInsertLink",!1,e)}var i;return b=tinymce.extend(b,e.data),(i=b.href)?i.indexOf("@")>0&&-1==i.indexOf("//")&&-1==i.indexOf("mailto:")?void n("The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",function(t){t&&(i="mailto:"+i),l()}):/^\s*www\./i.test(i)?void n("The URL you entered seems to be an external link. Do you want to add the required http:// prefix?",function(t){t&&(i="http://"+i),l()}):void l():void t.execCommand("unlink")}})}t.addButton("link",{icon:"link",tooltip:"Insert/edit link",shortcut:"Ctrl+K",onclick:e(n),stateSelector:"a[href]"}),t.addButton("unlink",{icon:"unlink",tooltip:"Remove link",cmd:"unlink",stateSelector:"a[href]"}),t.addShortcut("Ctrl+K","",e(n)),this.showDialog=n,t.addMenuItem("link",{icon:"link",text:"Insert link",shortcut:"Ctrl+K",onclick:e(n),stateSelector:"a[href]",context:"insert",prependToContext:!0})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/lists/plugin.min.js b/web/resource/components/tinymce/plugins/lists/plugin.min.js new file mode 100644 index 0000000..cf0e600 --- /dev/null +++ b/web/resource/components/tinymce/plugins/lists/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("lists",function(e){function t(e){return e&&/^(OL|UL|DL)$/.test(e.nodeName)}function n(e){return e.parentNode.firstChild==e}function r(e){return e.parentNode.lastChild==e}function a(t){return t&&!!e.schema.getTextBlockElements()[t.nodeName]}var o=this;e.on("init",function(){function i(e){function t(t){var r,a,o;a=e[t?"startContainer":"endContainer"],o=e[t?"startOffset":"endOffset"],1==a.nodeType&&(r=y.create("span",{"data-mce-type":"bookmark"}),a.hasChildNodes()?(o=Math.min(o,a.childNodes.length-1),t?a.insertBefore(r,a.childNodes[o]):y.insertAfter(r,a.childNodes[o])):a.appendChild(r),a=r,o=0),n[t?"startContainer":"endContainer"]=a,n[t?"startOffset":"endOffset"]=o}var n={};return t(!0),e.collapsed||t(),n}function d(e){function t(t){function n(e){for(var t=e.parentNode.firstChild,n=0;t;){if(t==e)return n;(1!=t.nodeType||"bookmark"!=t.getAttribute("data-mce-type"))&&n++,t=t.nextSibling}return-1}var r,a,o;r=o=e[t?"startContainer":"endContainer"],a=e[t?"startOffset":"endOffset"],r&&(1==r.nodeType&&(a=n(r),r=r.parentNode,y.remove(o)),e[t?"startContainer":"endContainer"]=r,e[t?"startOffset":"endOffset"]=a)}t(!0),t();var n=y.createRng();n.setStart(e.startContainer,e.startOffset),e.endContainer&&n.setEnd(e.endContainer,e.endOffset),k.setRng(n)}function s(t,n){var r,a,o,i=y.createFragment(),d=e.schema.getBlockElements();if(e.settings.forced_root_block&&(n=n||e.settings.forced_root_block),n&&(a=y.create(n),a.tagName===e.settings.forced_root_block&&y.setAttribs(a,e.settings.forced_root_block_attrs),i.appendChild(a)),t)for(;r=t.firstChild;){var s=r.nodeName;o||"SPAN"==s&&"bookmark"==r.getAttribute("data-mce-type")||(o=!0),d[s]?(i.appendChild(r),a=null):n?(a||(a=y.create(n),i.appendChild(a)),a.appendChild(r)):i.appendChild(r)}return e.settings.forced_root_block?o||tinymce.Env.ie&&!(tinymce.Env.ie>10)||a.appendChild(y.create("br",{"data-mce-bogus":"1"})):i.appendChild(y.create("br")),i}function f(){return tinymce.grep(k.getSelectedBlocks(),function(e){return/^(LI|DT|DD)$/.test(e.nodeName)})}function l(e,t,n){var r,a,o=y.select('span[data-mce-type="bookmark"]',e);n=n||s(t),r=y.createRng(),r.setStartAfter(t),r.setEndAfter(e),a=r.extractContents(),y.isEmpty(a)||y.insertAfter(a,e),y.insertAfter(n,e),y.isEmpty(t.parentNode)&&(tinymce.each(o,function(e){t.parentNode.parentNode.insertBefore(e,t.parentNode)}),y.remove(t.parentNode)),y.remove(t)}function c(e){var n,r;if(n=e.nextSibling,n&&t(n)&&n.nodeName==e.nodeName){for(;r=n.firstChild;)e.appendChild(r);y.remove(n)}if(n=e.previousSibling,n&&t(n)&&n.nodeName==e.nodeName){for(;r=n.firstChild;)e.insertBefore(r,e.firstChild);y.remove(n)}}function p(e){tinymce.each(tinymce.grep(y.select("ol,ul",e)),function(e){var n,r=e.parentNode;"LI"==r.nodeName&&r.firstChild==e&&(n=r.previousSibling,n&&"LI"==n.nodeName&&(n.appendChild(e),y.isEmpty(r)&&y.remove(r))),t(r)&&(n=r.previousSibling,n&&"LI"==n.nodeName&&n.appendChild(e))})}function m(e){function a(e){y.isEmpty(e)&&y.remove(e)}var o,i=e.parentNode,d=i.parentNode;return"DD"==e.nodeName?(y.rename(e,"DT"),!0):n(e)&&r(e)?("LI"==d.nodeName?(y.insertAfter(e,d),a(d),y.remove(i)):t(d)?y.remove(i,!0):(d.insertBefore(s(e),i),y.remove(i)),!0):n(e)?("LI"==d.nodeName?(y.insertAfter(e,d),e.appendChild(i),a(d)):t(d)?d.insertBefore(e,i):(d.insertBefore(s(e),i),y.remove(e)),!0):r(e)?("LI"==d.nodeName?y.insertAfter(e,d):t(d)?y.insertAfter(e,i):(y.insertAfter(s(e),i),y.remove(e)),!0):("LI"==d.nodeName?(i=d,o=s(e,"LI")):o=t(d)?s(e,"LI"):s(e),l(i,e,o),p(i.parentNode),!0)}function u(e){function n(n,r){var a;if(t(n)){for(;a=e.lastChild.firstChild;)r.appendChild(a);y.remove(n)}}var r,a;return"DT"==e.nodeName?(y.rename(e,"DD"),!0):(r=e.previousSibling,r&&t(r)?(r.appendChild(e),!0):r&&"LI"==r.nodeName&&t(r.lastChild)?(r.lastChild.appendChild(e),n(e.lastChild,r.lastChild),!0):(r=e.nextSibling,r&&t(r)?(r.insertBefore(e,r.firstChild),!0):r&&"LI"==r.nodeName&&t(e.lastChild)?!1:(r=e.previousSibling,r&&"LI"==r.nodeName?(a=y.create(e.parentNode.nodeName),r.appendChild(a),a.appendChild(e),n(e.lastChild,a),!0):!1)))}function h(){var t=f();if(t.length){for(var n=i(k.getRng(!0)),r=0;r0))return n;for(var a=new tinymce.dom.TreeWalker(e.startContainer);n=a[t?"next":"prev"]();)if(3==n.nodeType&&n.data.length>0)return n}function r(e,n){var r,a,o=e.parentNode;for(t(n.lastChild)&&(a=n.lastChild),r=n.lastChild,r&&"BR"==r.nodeName&&e.hasChildNodes()&&y.remove(r);r=e.firstChild;)n.appendChild(r);a&&n.appendChild(a),y.remove(e),y.isEmpty(o)&&y.remove(o)}if(k.isCollapsed()){var a=y.getParent(k.getStart(),"LI");if(a){var o=k.getRng(!0),s=y.getParent(n(o,e),"LI");if(s&&s!=a){var f=i(o);return e?r(s,a):r(a,s),d(f),!0}if(!s&&!e&&g(a.parentNode.nodeName))return!0}}},e.addCommand("Indent",function(){return h()?void 0:!0}),e.addCommand("Outdent",function(){return v()?void 0:!0}),e.addCommand("InsertUnorderedList",function(){N("UL")}),e.addCommand("InsertOrderedList",function(){N("OL")}),e.addCommand("InsertDefinitionList",function(){N("DL")}),e.addQueryStateHandler("InsertUnorderedList",L("UL")),e.addQueryStateHandler("InsertOrderedList",L("OL")),e.addQueryStateHandler("InsertDefinitionList",L("DL")),e.on("keydown",function(t){9==t.keyCode&&e.dom.getParent(e.selection.getStart(),"LI,DT,DD")&&(t.preventDefault(),t.shiftKey?v():h())})}),e.addButton("indent",{icon:"indent",title:"Increase indent",cmd:"Indent",onPostRender:function(){var t=this;e.on("nodechange",function(){for(var r=e.selection.getSelectedBlocks(),a=!1,o=0,i=r.length;!a&&i>o;o++){var d=r[o].nodeName;a="LI"==d&&n(r[o])||"UL"==d||"OL"==d||"DD"==d}t.disabled(a)})}}),e.on("keydown",function(e){e.keyCode==tinymce.util.VK.BACKSPACE?o.backspaceDelete()&&e.preventDefault():e.keyCode==tinymce.util.VK.DELETE&&o.backspaceDelete(!0)&&e.preventDefault()})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/media/plugin.min.js b/web/resource/components/tinymce/plugins/media/plugin.min.js new file mode 100644 index 0000000..cb1515c --- /dev/null +++ b/web/resource/components/tinymce/plugins/media/plugin.min.js @@ -0,0 +1,779 @@ +/** + * plugin.js + * + * Copyright, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +/*jshint maxlen:255 */ +/*eslint max-len:0 */ +/*global tinymce:true */ + +tinymce.PluginManager.add('media', function(editor, url) { + var urlPatterns = [ + {regex: /youtu\.be\/([\w\-.]+)/, type: 'iframe', w: '100%', h: '250px', url: '//www.youtube.com/embed/$1'}, + {regex: /youtube\.com(.+)v=([^&]+)/, type: 'iframe', w: '100%', h: '250px', url: '//www.youtube.com/embed/$2'}, + {regex: /vimeo\.com\/([0-9]+)/, type: 'iframe', w: '100%', h: '250px', url: '//player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc'}, + {regex: /vimeo\.com\/(.*)\/([0-9]+)/, type: "iframe", w: '100%', h: '250px', url: "//player.vimeo.com/video/$2?title=0&byline=0"}, + {regex: /maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/, type: 'iframe', w: '100%', h: '250px', url: '//maps.google.com/maps/ms?msid=$2&output=embed"'}, + {regex: /v\.youku\.com\/v_show\/id_([\w\-=]+)\.html/, type: 'iframe', w: '100%', h: '250px', url: '//player.youku.com/embed/$1'}, + {regex: /tudou\.com\/(listplay|albumplay)\/([\w\-=]+)\/([\w\-=]+)\.html/, type: 'iframe', w: '100%', h: '250px', url: '//www.tudou.com/programs/view/html5embed.action?type=0&code=$3&lcode='}, + {regex: /tudou\.com\/programs\/view\/([\w\-=]+)\//, type: 'iframe', w: '100%', h: '250px', url: '//www.tudou.com/programs/view/html5embed.action?type=0&code=$1&lcode='}, + {regex: /56\.com\/([\w\-=]+)\/v_([\w\-=]+)\.html/, type: 'iframe', w: '100%', h: '250px', url: '//www.56.com/iframe/$2"'}, + {regex: /v\.ku6\.com\/.+\/([\w\-=._]+)\.html.*$/, type: 'iframe', w: '100%', h: '250px', url: '//player.ku6.com/refer/$1/v.swf'} + ]; + + var embedChange = (tinymce.Env.ie && tinymce.Env.ie <= 8) ? 'onChange' : 'onInput'; + + function guessMime(url) { + if (url.indexOf('.mp3') != -1) { + return 'audio/mpeg'; + } + + if (url.indexOf('.wav') != -1) { + return 'audio/wav'; + } + + if (url.indexOf('.mp4') != -1) { + return 'video/mp4'; + } + + if (url.indexOf('.webm') != -1) { + return 'video/webm'; + } + + if (url.indexOf('.ogg') != -1) { + return 'video/ogg'; + } + + if (url.indexOf('.swf') != -1) { + return 'application/x-shockwave-flash'; + } + + return ''; + } + + function getVideoScriptMatch(src) { + var prefixes = editor.settings.media_scripts; + + if (prefixes) { + for (var i = 0; i < prefixes.length; i++) { + if (src.indexOf(prefixes[i].filter) !== -1) { + return prefixes[i]; + } + } + } + } + + function showDialog() { + var win, width, height, data; + + var generalFormItems = [ + { + name: 'source1', + type: 'filepicker', + filetype: 'media', + size: 40, + autofocus: true, + label: 'Source', + onchange: function(e) { + tinymce.each(e.meta, function(value, key) { + win.find('#' + key).value(value); + }); + } + } + ]; + + function recalcSize(e) { + var widthCtrl, heightCtrl, newWidth, newHeight; + + widthCtrl = win.find('#width')[0]; + heightCtrl = win.find('#height')[0]; + + newWidth = widthCtrl.value(); + newHeight = heightCtrl.value(); + + if (win.find('#constrain')[0].checked() && width && height && newWidth && newHeight) { + if (e.control == widthCtrl) { + newHeight = Math.round((newWidth / width) * newHeight); + heightCtrl.value(newHeight); + } else { + newWidth = Math.round((newHeight / height) * newWidth); + widthCtrl.value(newWidth); + } + } + + width = newWidth; + height = newHeight; + } + generalFormItems.push({type: 'label',text: '支持优酷、56、土豆、酷六',forId: ''}); + generalFormItems.push({type: 'label',text: '直接填写页面地址即可',forId: ''}); + generalFormItems.push({type: 'label',text: '其它视频请复制“通用代码”到内嵌中',forId: ''}); + if (editor.settings.media_alt_source !== false) { + generalFormItems.push({name: 'source2', type: 'filepicker', filetype: 'media', size: 40, label: 'Alternative source'}); + } + + if (editor.settings.media_poster !== false) { + generalFormItems.push({name: 'poster', type: 'filepicker', filetype: 'image', size: 40, label: 'Poster'}); + } + + if (editor.settings.media_dimensions !== false) { + generalFormItems.push({ + type: 'container', + label: 'Dimensions', + layout: 'flex', + align: 'center', + spacing: 5, + items: [ + {name: 'width', type: 'textbox', maxLength: 3, size: 3, onchange: recalcSize}, + {type: 'label', text: 'x'}, + {name: 'height', type: 'textbox', maxLength: 3, size: 3, onchange: recalcSize}, + {name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions'} + ] + }); + } + + data = getData(editor.selection.getNode()); + width = data.width; + height = data.height; + + var embedTextBox = { + id: 'mcemediasource', + type: 'textbox', + flex: 1, + name: 'embed', + value: getSource(), + multiline: true, + label: 'Source' + }; + + function updateValueOnChange() { + data = htmlToData(this.value()); + this.parent().parent().fromJSON(data); + } + + embedTextBox[embedChange] = updateValueOnChange; + + win = editor.windowManager.open({ + title: 'Insert/edit video', + data: data, + bodyType: 'tabpanel', + body: [ + { + title: 'General', + type: "form", + onShowTab: function() { + data = htmlToData(this.next().find('#embed').value()); + this.fromJSON(data); + }, + items: generalFormItems + }, + + { + title: 'Embed', + type: "panel", + layout: 'flex', + direction: 'column', + align: 'stretch', + padding: 10, + spacing: 10, + onShowTab: function() { + this.find('#embed').value(dataToHtml(this.parent().toJSON())); + }, + items: [ + { + type: 'label', + text: 'Paste your embed code below:', + forId: 'mcemediasource' + }, + embedTextBox + ] + } + ], + onSubmit: function() { + var beforeObjects, afterObjects, i, y; + + beforeObjects = editor.dom.select('img[data-mce-object]'); + editor.insertContent(dataToHtml(this.toJSON())); + afterObjects = editor.dom.select('img[data-mce-object]'); + + // Find new image placeholder so we can select it + for (i = 0; i < beforeObjects.length; i++) { + for (y = afterObjects.length - 1; y >= 0; y--) { + if (beforeObjects[i] == afterObjects[y]) { + afterObjects.splice(y, 1); + } + } + } + + editor.selection.select(afterObjects[0]); + editor.nodeChanged(); + } + }); + } + + function getSource() { + var elm = editor.selection.getNode(); + + if (elm.getAttribute('data-mce-object')) { + return editor.selection.getContent(); + } + } + + function dataToHtml(data) { + var html = ''; + if (!data.source1) { + tinymce.extend(data, htmlToData(data.embed)); + if (!data.source1) { + return ''; + } + } + + if (!data.source2) { + data.source2 = ''; + } + + if (!data.poster) { + data.poster = ''; + } + + data.source1 = editor.convertURL(data.source1, "source"); + data.source2 = editor.convertURL(data.source2, "source"); + data.source1mime = guessMime(data.source1); + data.source2mime = guessMime(data.source2); + data.poster = editor.convertURL(data.poster, "poster"); + data.flashPlayerUrl = editor.convertURL(url + '/moxieplayer.swf', "movie"); + + tinymce.each(urlPatterns, function(pattern) { + var match, i, url; + + if ((match = pattern.regex.exec(data.source1))) { + url = pattern.url; + + for (i = 0; match[i]; i++) { + /*jshint loopfunc:true*/ + /*eslint no-loop-func:0 */ + url = url.replace('$' + i, function() { + return match[i]; + }); + } + + data.source1 = url; + data.type = pattern.type; + data.width = data.width || pattern.w; + data.height = data.height || pattern.h; + } + }); + + if (data.embed) { + html = updateHtml(data.embed, data, true); + } else { + var videoScript = getVideoScriptMatch(data.source1); + if (videoScript) { + data.type = 'script'; + data.width = videoScript.width; + data.height = videoScript.height; + } + + data.width = data.width || 300; + data.height = data.height || 150; + + tinymce.each(data, function(value, key) { + data[key] = editor.dom.encode(value); + }); + + if (data.type == "iframe") { + html += ''; + } else if (data.source1mime == "application/x-shockwave-flash") { + html += ''; + + if (data.poster) { + html += ''; + } + + html += ''; + } else if (data.source1mime.indexOf('audio') != -1) { + if (editor.settings.audio_template_callback) { + html = editor.settings.audio_template_callback(data); + } else { + html += ( + '' + ); + } + } else if (data.type == "script") { + html += ''; + } else { + if (editor.settings.video_template_callback) { + html = editor.settings.video_template_callback(data); + } else { + html = ( + '' + ); + } + } + } + + return html; + } + + function htmlToData(html) { + var data = {}; + + new tinymce.html.SaxParser({ + validate: false, + allow_conditional_comments: true, + special: 'script,noscript', + start: function(name, attrs) { + if (!data.source1 && name == "param") { + data.source1 = attrs.map.movie; + } + + if (name == "iframe" || name == "object" || name == "embed" || name == "video" || name == "audio") { + if (!data.type) { + data.type = name; + } + + data = tinymce.extend(attrs.map, data); + } + + if (name == "script") { + var videoScript = getVideoScriptMatch(attrs.map.src); + if (!videoScript) { + return; + } + + data = { + type: "script", + source1: attrs.map.src, + width: videoScript.width, + height: videoScript.height + }; + } + + if (name == "source") { + if (!data.source1) { + data.source1 = attrs.map.src; + } else if (!data.source2) { + data.source2 = attrs.map.src; + } + } + + if (name == "img" && !data.poster) { + data.poster = attrs.map.src; + } + } + }).parse(html); + + data.source1 = data.source1 || data.src || data.data; + data.source2 = data.source2 || ''; + data.poster = data.poster || ''; + + return data; + } + + function getData(element) { + if (element.getAttribute('data-mce-object')) { + return htmlToData(editor.serializer.serialize(element, {selection: true})); + } + + return {}; + } + + function sanitize(html) { + if (editor.settings.media_filter_html === false) { + return html; + } + + var writer = new tinymce.html.Writer(); + + new tinymce.html.SaxParser({ + validate: false, + allow_conditional_comments: false, + special: 'script,noscript', + + comment: function(text) { + writer.comment(text); + }, + + cdata: function(text) { + writer.cdata(text); + }, + + text: function(text, raw) { + writer.text(text, raw); + }, + + start: function(name, attrs, empty) { + if (name == 'script' || name == 'noscript') { + return; + } + + for (var i = 0; i < attrs.length; i++) { + if (attrs[i].name.indexOf('on') === 0) { + return; + } + } + + writer.start(name, attrs, empty); + }, + + end: function(name) { + if (name == 'script' || name == 'noscript') { + return; + } + + writer.end(name); + } + }, new tinymce.html.Schema({})).parse(html); + + return writer.getContent(); + } + + function updateHtml(html, data, updateAll) { + var writer = new tinymce.html.Writer(); + var sourceCount = 0, hasImage; + + function setAttributes(attrs, updatedAttrs) { + var name, i, value, attr; + + for (name in updatedAttrs) { + value = "" + updatedAttrs[name]; + + if (attrs.map[name]) { + i = attrs.length; + while (i--) { + attr = attrs[i]; + + if (attr.name == name) { + if (value) { + attrs.map[name] = value; + attr.value = value; + } else { + delete attrs.map[name]; + attrs.splice(i, 1); + } + } + } + } else if (value) { + attrs.push({ + name: name, + value: value + }); + + attrs.map[name] = value; + } + } + } + + new tinymce.html.SaxParser({ + validate: false, + allow_conditional_comments: true, + special: 'script,noscript', + + comment: function(text) { + writer.comment(text); + }, + + cdata: function(text) { + writer.cdata(text); + }, + + text: function(text, raw) { + writer.text(text, raw); + }, + + start: function(name, attrs, empty) { + switch (name) { + case "video": + case "object": + case "embed": + case "img": + case "iframe": + setAttributes(attrs, { + style: 'width:'+data.width+'; height:'+data.height+';' + }); + break; + } + + if (updateAll) { + switch (name) { + case "video": + setAttributes(attrs, { + poster: data.poster, + src: "" + }); + + if (data.source2) { + setAttributes(attrs, { + src: "" + }); + } + break; + + case "iframe": + setAttributes(attrs, { + src: data.source1 + }); + break; + + case "source": + sourceCount++; + + if (sourceCount <= 2) { + setAttributes(attrs, { + src: data["source" + sourceCount], + type: data["source" + sourceCount + "mime"] + }); + + if (!data["source" + sourceCount]) { + return; + } + } + break; + + case "img": + if (!data.poster) { + return; + } + + hasImage = true; + break; + } + } + + writer.start(name, attrs, empty); + }, + + end: function(name) { + if (name == "video" && updateAll) { + for (var index = 1; index <= 2; index++) { + if (data["source" + index]) { + var attrs = []; + attrs.map = {}; + + if (sourceCount < index) { + setAttributes(attrs, { + src: data["source" + index], + type: data["source" + index + "mime"] + }); + + writer.start("source", attrs, true); + } + } + } + } + + if (data.poster && name == "object" && updateAll && !hasImage) { + var imgAttrs = []; + imgAttrs.map = {}; + + setAttributes(imgAttrs, { + src: data.poster, + width: data.width, + height: data.height + }); + + writer.start("img", imgAttrs, true); + } + + writer.end(name); + } + }, new tinymce.html.Schema({})).parse(html); + + return writer.getContent(); + } + + editor.on('ResolveName', function(e) { + var name; + + if (e.target.nodeType == 1 && (name = e.target.getAttribute("data-mce-object"))) { + e.name = name; + } + }); + + editor.on('preInit', function() { + // Make sure that any messy HTML is retained inside these + var specialElements = editor.schema.getSpecialElements(); + tinymce.each('video audio iframe object'.split(' '), function(name) { + specialElements[name] = new RegExp('<\/' + name + '[^>]*>', 'gi'); + }); + + // Allow elements + //editor.schema.addValidElements('object[id|style|width|height|classid|codebase|*],embed[id|style|width|height|type|src|*],video[*],audio[*]'); + + // Set allowFullscreen attribs as boolean + var boolAttrs = editor.schema.getBoolAttrs(); + tinymce.each('webkitallowfullscreen mozallowfullscreen allowfullscreen'.split(' '), function(name) { + boolAttrs[name] = {}; + }); + + // Converts iframe, video etc into placeholder images + editor.parser.addNodeFilter('iframe,video,audio,object,embed,script', function(nodes, name) { + var i = nodes.length, ai, node, placeHolder, attrName, attrValue, attribs, innerHtml; + var videoScript; + + while (i--) { + node = nodes[i]; + if (!node.parent) { + continue; + } + + if (node.name == 'script') { + videoScript = getVideoScriptMatch(node.attr('src')); + if (!videoScript) { + continue; + } + } + + placeHolder = new tinymce.html.Node('img', 1); + placeHolder.shortEnded = true; + + if (videoScript) { + if (videoScript.width) { + node.attr('width', videoScript.width.toString()); + } + + if (videoScript.height) { + node.attr('height', videoScript.height.toString()); + } + } + + // Prefix all attributes except width, height and style since we + // will add these to the placeholder + attribs = node.attributes; + ai = attribs.length; + while (ai--) { + attrName = attribs[ai].name; + attrValue = attribs[ai].value; + + if (attrName !== "width" && attrName !== "height" && attrName !== "style") { + if (attrName == "data" || attrName == "src") { + attrValue = editor.convertURL(attrValue, attrName); + } + + placeHolder.attr('data-mce-p-' + attrName, attrValue); + } + } + + // Place the inner HTML contents inside an escaped attribute + // This enables us to copy/paste the fake object + innerHtml = node.firstChild && node.firstChild.value; + if (innerHtml) { + placeHolder.attr("data-mce-html", escape(innerHtml)); + placeHolder.firstChild = null; + } + + placeHolder.attr({ + width: node.attr('width') || "300", + height: node.attr('height') || (name == "audio" ? "30" : "150"), + style: node.attr('style'), + src: tinymce.Env.transparentSrc, + "data-mce-object": name, + "class": "mce-object mce-object-" + name + }); + + node.replace(placeHolder); + } + }); + + // Replaces placeholder images with real elements for video, object, iframe etc + editor.serializer.addAttributeFilter('data-mce-object', function(nodes, name) { + var i = nodes.length, node, realElm, ai, attribs, innerHtml, innerNode, realElmName; + + while (i--) { + node = nodes[i]; + if (!node.parent) { + continue; + } + + realElmName = node.attr(name); + realElm = new tinymce.html.Node(realElmName, 1); + + // Add width/height to everything but audio + if (realElmName != "audio" && realElmName != "script") { + realElm.attr({ + width: node.attr('width'), + height: node.attr('height') + }); + } + + realElm.attr({ + style: node.attr('style') + }); + + // Unprefix all placeholder attributes + attribs = node.attributes; + ai = attribs.length; + while (ai--) { + var attrName = attribs[ai].name; + + if (attrName.indexOf('data-mce-p-') === 0) { + realElm.attr(attrName.substr(11), attribs[ai].value); + } + } + + if (realElmName == "script") { + realElm.attr('type', 'text/javascript'); + } + + // Inject innerhtml + innerHtml = node.attr('data-mce-html'); + if (innerHtml) { + innerNode = new tinymce.html.Node('#text', 3); + innerNode.raw = true; + innerNode.value = sanitize(unescape(innerHtml)); + realElm.append(innerNode); + } + + node.replace(realElm); + } + }); + }); + + editor.on('ObjectSelected', function(e) { + var objectType = e.target.getAttribute('data-mce-object'); + + if (objectType == "audio" || objectType == "script") { + e.preventDefault(); + } + }); + + editor.on('objectResized', function(e) { + var target = e.target, html; + + if (target.getAttribute('data-mce-object')) { + html = target.getAttribute('data-mce-html'); + if (html) { + html = unescape(html); + target.setAttribute('data-mce-html', escape( + updateHtml(html, { + width: e.width, + height: e.height + }) + )); + } + } + }); + + editor.addButton('media', { + tooltip: 'Insert/edit video', + onclick: showDialog, + stateSelector: ['img[data-mce-object=video]', 'img[data-mce-object=iframe]'] + }); + + editor.addMenuItem('media', { + icon: 'media', + text: 'Insert video', + onclick: showDialog, + context: 'insert', + prependToContext: true + }); +}); diff --git a/web/resource/components/tinymce/plugins/multiimage/plugin.min.js b/web/resource/components/tinymce/plugins/multiimage/plugin.min.js new file mode 100644 index 0000000..2a67636 --- /dev/null +++ b/web/resource/components/tinymce/plugins/multiimage/plugin.min.js @@ -0,0 +1,38 @@ +tinymce.PluginManager.add('multiimage', function(editor) { + function handleImageDialog() { + var dom = editor.dom; + var imgElm = editor.selection.getNode(); + require(['util'], function(u){ + var v = ''; + if (imgElm && imgElm.tagName.toLowerCase() == 'img') { + v = imgElm.src; + } + u.uploadMultiPictures(function(list){ + for(var i=0;i 
':" "),n.dom.setAttrib(n.dom.select("span.mce-nbsp"),"data-mce-bogus","1")}),n.addButton("nonbreaking",{title:"Insert nonbreaking space",cmd:"mceNonBreaking"}),n.addMenuItem("nonbreaking",{text:"Nonbreaking space",cmd:"mceNonBreaking",context:"insert"}),e){var a=+e>1?+e:3;n.on("keydown",function(e){if(9==e.keyCode){if(e.shiftKey)return;e.preventDefault();for(var t=0;a>t;t++)n.execCommand("mceNonBreaking")}})}}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/noneditable/plugin.min.js b/web/resource/components/tinymce/plugins/noneditable/plugin.min.js new file mode 100644 index 0000000..aa642de --- /dev/null +++ b/web/resource/components/tinymce/plugins/noneditable/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("noneditable",function(e){function t(e){var t;if(1===e.nodeType){if(t=e.getAttribute(u),t&&"inherit"!==t)return t;if(t=e.contentEditable,"inherit"!==t)return t}return null}function n(e){for(var n;e;){if(n=t(e))return"false"===n?e:null;e=e.parentNode}}function r(){function r(e){for(;e;){if(e.id===g)return e;e=e.parentNode}}function a(e){var t;if(e)for(t=new f(e,e),e=t.current();e;e=t.next())if(3===e.nodeType)return e}function i(n,r){var a,i;return"false"===t(n)&&u.isBlock(n)?void s.select(n):(i=u.createRng(),"true"===t(n)&&(n.firstChild||n.appendChild(e.getDoc().createTextNode(" ")),n=n.firstChild,r=!0),a=u.create("span",{id:g,"data-mce-bogus":!0},m),r?n.parentNode.insertBefore(a,n):u.insertAfter(a,n),i.setStart(a.firstChild,1),i.collapse(!0),s.setRng(i),a)}function o(e){var t,n,i,o;if(e)t=s.getRng(!0),t.setStartBefore(e),t.setEndBefore(e),n=a(e),n&&n.nodeValue.charAt(0)==m&&(n=n.deleteData(0,1)),u.remove(e,!0),s.setRng(t);else for(i=r(s.getStart());(e=u.get(g))&&e!==o;)i!==e&&(n=a(e),n&&n.nodeValue.charAt(0)==m&&(n=n.deleteData(0,1)),u.remove(e,!0)),o=e}function l(){function e(e,n){var r,a,i,o,l;if(r=d.startContainer,a=d.startOffset,3==r.nodeType){if(l=r.nodeValue.length,a>0&&l>a||(n?a==l:0===a))return}else{if(!(a0?a-1:a;r=r.childNodes[u],r.hasChildNodes()&&(r=r.firstChild)}for(i=new f(r,e);o=i[n?"prev":"next"]();){if(3===o.nodeType&&o.nodeValue.length>0)return;if("true"===t(o))return o}return e}var r,a,l,d,u;o(),l=s.isCollapsed(),r=n(s.getStart()),a=n(s.getEnd()),(r||a)&&(d=s.getRng(!0),l?(r=r||a,(u=e(r,!0))?i(u,!0):(u=e(r,!1))?i(u,!1):s.select(r)):(d=s.getRng(!0),r&&d.setStartBefore(r),a&&d.setEndAfter(a),s.setRng(d)))}function d(a){function i(e,t){for(;e=e[t?"previousSibling":"nextSibling"];)if(3!==e.nodeType||e.nodeValue.length>0)return e}function d(e,t){s.select(e),s.collapse(t)}function g(a){function i(e){for(var t=d;t;){if(t===e)return;t=t.parentNode}u.remove(e),l()}function o(){var r,o,l=e.schema.getNonEmptyElements();for(o=new tinymce.dom.TreeWalker(d,e.getBody());(r=a?o.prev():o.next())&&!l[r.nodeName.toLowerCase()]&&!(3===r.nodeType&&tinymce.trim(r.nodeValue).length>0);)if("false"===t(r))return i(r),!0;return n(r)?!0:!1}var f,d,c,g;if(s.isCollapsed()){if(f=s.getRng(!0),d=f.startContainer,c=f.startOffset,d=r(d)||d,g=n(d))return i(g),!1;if(3==d.nodeType&&(a?c>0:ch||h>124)&&h!=c.DELETE&&h!=c.BACKSPACE){if((tinymce.isMac?a.metaKey:a.ctrlKey)&&(67==h||88==h||86==h))return;if(a.preventDefault(),h==c.LEFT||h==c.RIGHT){var y=h==c.LEFT;if(e.dom.isBlock(m)){var T=y?m.previousSibling:m.nextSibling,C=new f(T,T),b=y?C.prev():C.next();d(b,!y)}else d(m,y)}}else if(h==c.LEFT||h==c.RIGHT||h==c.BACKSPACE||h==c.DELETE){if(p=r(v)){if(h==c.LEFT||h==c.BACKSPACE)if(m=i(p,!0),m&&"false"===t(m)){if(a.preventDefault(),h!=c.LEFT)return void u.remove(m);d(m,!0)}else o(p);if(h==c.RIGHT||h==c.DELETE)if(m=i(p),m&&"false"===t(m)){if(a.preventDefault(),h!=c.RIGHT)return void u.remove(m);d(m,!1)}else o(p)}if((h==c.BACKSPACE||h==c.DELETE)&&!g(h==c.BACKSPACE))return a.preventDefault(),!1}}var u=e.dom,s=e.selection,g="mce_noneditablecaret",m="";e.on("mousedown",function(n){var r=e.selection.getNode();"false"===t(r)&&r==n.target&&l()}),e.on("mouseup keyup",l),e.on("keydown",d)}function a(t){var n=l.length,r=t.content,a=tinymce.trim(o);if("raw"!=t.format){for(;n--;)r=r.replace(l[n],function(t){var n=arguments,i=n[n.length-2];return i>0&&'"'==r.charAt(i-1)?t:''+e.dom.encode("string"==typeof n[1]?n[1]:n[0])+""});t.content=r}}var i,o,l,f=tinymce.dom.TreeWalker,d="contenteditable",u="data-mce-"+d,c=tinymce.util.VK;i=" "+tinymce.trim(e.getParam("noneditable_editable_class","mceEditable"))+" ",o=" "+tinymce.trim(e.getParam("noneditable_noneditable_class","mceNonEditable"))+" ",l=e.getParam("noneditable_regexp"),l&&!l.length&&(l=[l]),e.on("PreInit",function(){r(),l&&e.on("BeforeSetContent",a),e.parser.addAttributeFilter("class",function(e){for(var t,n,r=e.length;r--;)n=e[r],t=" "+n.attr("class")+" ",-1!==t.indexOf(i)?n.attr(u,"true"):-1!==t.indexOf(o)&&n.attr(u,"false")}),e.serializer.addAttributeFilter(u,function(e){for(var t,n=e.length;n--;)t=e[n],l&&t.attr("data-mce-content")?(t.name="#text",t.type=3,t.raw=!0,t.value=t.attr("data-mce-content")):(t.attr(d,null),t.attr(u,null))}),e.parser.addAttributeFilter(d,function(e){for(var t,n=e.length;n--;)t=e[n],t.attr(u,t.attr(d)),t.attr(d,null)})}),e.on("drop",function(e){n(e.target)&&e.preventDefault()})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/pagebreak/plugin.min.js b/web/resource/components/tinymce/plugins/pagebreak/plugin.min.js new file mode 100644 index 0000000..e232c05 --- /dev/null +++ b/web/resource/components/tinymce/plugins/pagebreak/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("pagebreak",function(e){var a="mce-pagebreak",t=e.getParam("pagebreak_separator",""),n=new RegExp(t.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(e){return"\\"+e}),"gi"),r='';e.addCommand("mcePageBreak",function(){e.insertContent(e.settings.pagebreak_split_block?"

"+r+"

":r)}),e.addButton("pagebreak",{title:"Page break",cmd:"mcePageBreak"}),e.addMenuItem("pagebreak",{text:"Page break",icon:"pagebreak",cmd:"mcePageBreak",context:"insert"}),e.on("ResolveName",function(t){"IMG"==t.target.nodeName&&e.dom.hasClass(t.target,a)&&(t.name="pagebreak")}),e.on("click",function(t){t=t.target,"IMG"===t.nodeName&&e.dom.hasClass(t,a)&&e.selection.select(t)}),e.on("BeforeSetContent",function(e){e.content=e.content.replace(n,r)}),e.on("PreInit",function(){e.serializer.addNodeFilter("img",function(a){for(var n,r,c=a.length;c--;)if(n=a[c],r=n.attr("class"),r&&-1!==r.indexOf("mce-pagebreak")){var o=n.parent;if(e.schema.getBlockElements()[o.name]&&e.settings.pagebreak_split_block){o.type=3,o.value=t,o.raw=!0,n.remove();continue}n.type=3,n.value=t,n.raw=!0}})})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/paste/plugin.min.js b/web/resource/components/tinymce/plugins/paste/plugin.min.js new file mode 100644 index 0000000..52fa8bd --- /dev/null +++ b/web/resource/components/tinymce/plugins/paste/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;i]*>\s*|\s*<\/body[^>]*>[\s\S]*$/g,/|/g,[/\u00a0<\/span>/g,"\xa0"],/
$/i])}return{filter:r,innerText:i,trimHtml:o}}),r(f,[p,m,l],function(e,t,n){return function(r){function i(e){var t,n=r.dom;if(t=r.fire("BeforePastePreProcess",{content:e}),t=r.fire("PastePreProcess",t),e=t.content,!t.isDefaultPrevented()){if(r.hasEventListeners("PastePostProcess")&&!t.isDefaultPrevented()){var i=n.add(r.getBody(),"div",{style:"display:none"},e);t=r.fire("PastePostProcess",{node:i}),n.remove(i),e=t.node.innerHTML}t.isDefaultPrevented()||r.insertContent(e,{merge:r.settings.paste_merge_formats!==!1})}}function o(e){e=r.dom.encode(e).replace(/\r\n/g,"\n");var t=r.dom.getParent(r.selection.getStart(),r.dom.isBlock),o=r.settings.forced_root_block,a;o&&(a=r.dom.createHTML(o,r.settings.forced_root_block_attrs),a=a.substr(0,a.length-3)+">"),t&&/^(PRE|DIV)$/.test(t.nodeName)||!o?e=n.filter(e,[[/\n/g,"
"]]):(e=n.filter(e,[[/\n\n/g,"

"+a],[/^(.*<\/p>)(

)$/,a+"$1"],[/\n/g,"
"]]),-1!=e.indexOf("

")&&(e=a+e)),i(e)}function a(){var t=r.dom,n=r.getBody(),i=r.dom.getViewPort(r.getWin()),o=i.y,a=20,s;if(b=r.selection.getRng(),r.inline&&(s=r.selection.getScrollContainer(),s&&s.scrollTop>0&&(o=s.scrollTop)),b.getClientRects){var l=b.getClientRects();if(l.length)a=o+(l[0].top-t.getPos(n).y);else{a=o;var c=b.startContainer;c&&(3==c.nodeType&&c.parentNode!=n&&(c=c.parentNode),1==c.nodeType&&(a=t.getPos(c,s||n).y))}}y=t.add(r.getBody(),"div",{id:"mcepastebin",contentEditable:!0,"data-mce-bogus":"1",style:"position: absolute; top: "+a+"px;width: 10px; height: 10px; overflow: hidden; opacity: 0"},x),(e.ie||e.gecko)&&t.setStyle(y,"left","rtl"==t.getStyle(n,"direction",!0)?65535:-65535),t.bind(y,"beforedeactivate focusin focusout",function(e){e.stopPropagation()}),y.focus(),r.selection.select(y,!0)}function s(){if(y){for(var e;e=r.dom.get("mcepastebin");)r.dom.remove(e),r.dom.unbind(e);b&&r.selection.setRng(b)}y=b=null}function l(){var e=x,t,n;for(t=r.dom.select("div[id=mcepastebin]"),n=t.length;n--;){var i=t[n].innerHTML;e==x&&(e=""),i.length>e.length&&(e=i)}return e}function c(e){var t={};if(e&&e.types){var n=e.getData("Text");n&&n.length>0&&(t["text/plain"]=n);for(var r=0;r')},t.readAsDataURL(e.getAsFile()),!0}}if(!(!r.settings.paste_data_images||"text/html"in t||"text/plain"in t)&&e.clipboardData){var o=e.clipboardData.items;if(o)for(var a=0;a0}function h(e){return t.metaKeyPressed(e)&&86==e.keyCode||e.shiftKey&&45==e.keyCode}function g(){r.on("keydown",function(t){if(h(t)&&!t.isDefaultPrevented()){if(w=t.shiftKey&&86==t.keyCode,w&&e.webkit&&-1!=navigator.userAgent.indexOf("Version/"))return;if(t.stopImmediatePropagation(),C=(new Date).getTime(),e.ie&&w)return t.preventDefault(),void r.fire("paste",{ieFake:!0});s(),a()}}),r.on("keyup",function(e){h(e)&&!e.isDefaultPrevented()&&s()}),r.on("paste",function(t){var c=d(t),p=(new Date).getTime()-C<1e3,h="text"==v.pasteFormat||w;return w=!1,t.isDefaultPrevented()||f(t)?void s():u(t,c)?void s():(p||t.preventDefault(),!e.ie||p&&!t.ieFake||(a(),r.dom.bind(y,"paste",function(e){e.stopPropagation()}),r.getDoc().execCommand("Paste",!1,null),c["text/html"]=l()),void setTimeout(function(){var e;return m(c,"text/html")?e=c["text/html"]:(e=l(),e==x&&(h=!0)),e=n.trimHtml(l()),y&&y.firstChild&&"mcepastebin"===y.firstChild.id&&(h=!0),s(),h&&(e=m(c,"text/plain")&&-1==e.indexOf("

")?c["text/plain"]:n.innerText(e)),e==x?void(p||r.windowManager.alert("Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.")):void(h?o(e):i(e))},0))}),r.on("dragstart",function(e){if(e.dataTransfer.types)try{e.dataTransfer.setData("mce-internal",r.selection.getContent())}catch(t){}}),r.on("drop",function(e){var t=p(e);if(t&&!e.isDefaultPrevented()){var n=c(e.dataTransfer),a=n["mce-internal"]||n["text/html"]||n["text/plain"];a&&(e.preventDefault(),r.undoManager.transact(function(){n["mce-internal"]&&r.execCommand("Delete"),r.selection.setRng(t),n["text/html"]?i(a):o(a)}))}})}var v=this,y,b,C=0,x="%MCEPASTEBIN%",w;v.pasteHtml=i,v.pasteText=o,r.on("preInit",function(){g(),r.parser.addNodeFilter("img",function(t){if(!r.settings.paste_data_images)for(var n=t.length;n--;){var i=t[n].attributes.map.src;i&&0===i.indexOf("data:image")&&(t[n].attr("data-mce-object")||i===e.transparentSrc||t[n].remove())}})}),r.on("BeforeAddUndo",function(e){e.level.content&&(e.level.content=e.level.content.replace(/
]+>%MCEPASTEBIN%<\/div>/gi,""))})}}),r(h,[c,d,u,g,v,l],function(e,t,n,r,i,o){function a(e){return/l?n&&(n=n.parent.parent):(r=n,n=null)),n&&n.name==a?n.append(e):(r=r||n,n=new i(a,1),s>1&&n.attr("start",""+s),e.wrap(n)),e.name="li",t.value="";var c=t.next;c&&3==c.type&&(c.value=c.value.replace(/^\u00a0+/,"")),l>o&&r&&r.lastChild.append(n),o=l}for(var n,r,o=1,a=e.getAll("p"),s=0;s/gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/([\s\u00a0]*)<\/span>/gi,function(e,t){return t.length>0?t.replace(/./," ").slice(Math.floor(t.length/2)).split("").join("\xa0"):""}]]);var h=l.paste_word_valid_elements;h||(h="-strong/b,-em/i,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-p/div,-table[width],-tr,-td[colspan|rowspan|width],-th,-thead,-tfoot,-tbody,-a[href|name],sub,sup,strike,br,del");var g=new n({valid_elements:h,valid_children:"-li[p]"});e.each(g.elements,function(e){e.attributes["class"]||(e.attributes["class"]={},e.attributesOrder.push("class")),e.attributes.style||(e.attributes.style={},e.attributesOrder.push("style"))});var v=new t({},g);v.addAttributeFilter("style",function(e){for(var t=e.length,n;t--;)n=e[t],n.attr("style",u(n,n.attr("style"))),"span"==n.name&&n.parent&&!n.attributes.length&&n.unwrap()}),v.addAttributeFilter("class",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.attr("class"),/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(r)&&n.remove(),n.attr("class",null)}),v.addNodeFilter("del",function(e){for(var t=e.length;t--;)e[t].remove()}),v.addNodeFilter("a",function(e){for(var t=e.length,n,r,i;t--;)if(n=e[t],r=n.attr("href"),i=n.attr("name"),r&&-1!=r.indexOf("#_msocom_"))n.remove();else if(r&&0===r.indexOf("file://")&&(r=r.split("#")[1],r&&(r="#"+r)),r||i){if(i&&!/^_?(?:toc|edn|ftn)/i.test(i)){n.unwrap();continue}n.attr({href:r,name:i})}else n.unwrap()});var y=v.parse(f);d(y),c.content=new r({},g).serialize(y)}})}return s.isWordContent=a,s}),r(y,[p,c,h,l],function(e,t,n,r){return function(i){function o(e){i.on("BeforePastePreProcess",function(t){t.content=e(t.content)})}function a(e){if(!n.isWordContent(e))return e;var o=[];t.each(i.schema.getBlockElements(),function(e,t){o.push(t)});var a=new RegExp("(?:
 [\\s\\r\\n]+|
)*(<\\/?("+o.join("|")+")[^>]*>)(?:
 [\\s\\r\\n]+|
)*","g");return e=r.filter(e,[[a,"$1"]]),e=r.filter(e,[[/

/g,"

"],[/
/g," "],[/

/g,"
"]])}function s(e){if(n.isWordContent(e))return e;var t=i.settings.paste_webkit_styles;if(i.settings.paste_remove_styles_if_webkit===!1||"all"==t)return e;if(t&&(t=t.split(/[, ]/)),t){var r=i.dom,o=i.selection.getNode();e=e.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi,function(e,n,i,a){var s=r.parseStyle(i,"span"),l={};if("none"===t)return n+a;for(var c=0;c]+) style="([^"]*)"([^>]*>)/gi,"$1$3");return e=e.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi,function(e,t,n,r){return t+' style="'+n+'"'+r})}e.webkit&&o(s),e.ie&&o(a)}}),r(b,[C,f,h,y],function(e,t,n,r){var i;e.add("paste",function(e){function o(){"text"==s.pasteFormat?(this.active(!1),s.pasteFormat="html"):(s.pasteFormat="text",this.active(!0),i||(e.windowManager.alert("Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off."),i=!0))}var a=this,s,l=e.settings;a.clipboard=s=new t(e),a.quirks=new r(e),a.wordFilter=new n(e),e.settings.paste_as_text&&(a.clipboard.pasteFormat="text"),l.paste_preprocess&&e.on("PastePreProcess",function(e){l.paste_preprocess.call(a,a,e)}),l.paste_postprocess&&e.on("PastePostProcess",function(e){l.paste_postprocess.call(a,a,e)}),e.addCommand("mceInsertClipboardContent",function(e,t){t.content&&a.clipboard.pasteHtml(t.content),t.text&&a.clipboard.pasteText(t.text)}),e.paste_block_drop&&e.on("dragend dragover draggesture dragdrop drop drag",function(e){e.preventDefault(),e.stopPropagation()}),e.settings.paste_data_images||e.on("drop",function(e){var t=e.dataTransfer;t&&t.files&&t.files.length>0&&e.preventDefault()}),e.addButton("pastetext",{icon:"pastetext",tooltip:"Paste as text",onclick:o,active:"text"==a.clipboard.pasteFormat}),e.addMenuItem("pastetext",{text:"Paste as text",selectable:!0,active:s.pasteFormat,onclick:o})})}),a([l,h])}(this); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/preview/plugin.min.js b/web/resource/components/tinymce/plugins/preview/plugin.min.js new file mode 100644 index 0000000..23e70ac --- /dev/null +++ b/web/resource/components/tinymce/plugins/preview/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("preview",function(e){var t=e.settings,i=!tinymce.Env.ie;e.addCommand("mcePreview",function(){e.windowManager.open({title:"Preview",width:parseInt(e.getParam("plugin_preview_width","650"),10),height:parseInt(e.getParam("plugin_preview_height","500"),10),html:'",buttons:{text:"Close",onclick:function(){this.parent().parent().close()}},onPostRender:function(){var n,a="";a+='',tinymce.each(e.contentCSS,function(t){a+=''});var r=t.body_id||"tinymce";-1!=r.indexOf("=")&&(r=e.getParam("body_id","","hash"),r=r[e.id]||r);var d=t.body_class||"";-1!=d.indexOf("=")&&(d=e.getParam("body_class","","hash"),d=d[e.id]||"");var o=e.settings.directionality?' dir="'+e.settings.directionality+'"':"";if(n=""+a+'"+e.getContent()+"",i)this.getEl("body").firstChild.src="data:text/html;charset=utf-8,"+encodeURIComponent(n);else{var s=this.getEl("body").firstChild.contentWindow.document;s.open(),s.write(n),s.close()}}})}),e.addButton("preview",{title:"Preview",cmd:"mcePreview"}),e.addMenuItem("preview",{text:"Preview",cmd:"mcePreview",context:"view"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/print/plugin.min.js b/web/resource/components/tinymce/plugins/print/plugin.min.js new file mode 100644 index 0000000..abc37b5 --- /dev/null +++ b/web/resource/components/tinymce/plugins/print/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("print",function(t){t.addCommand("mcePrint",function(){t.getWin().print()}),t.addButton("print",{title:"Print",cmd:"mcePrint"}),t.addShortcut("Ctrl+P","","mcePrint"),t.addMenuItem("print",{text:"Print",cmd:"mcePrint",icon:"print",shortcut:"Ctrl+P",context:"file"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/save/plugin.min.js b/web/resource/components/tinymce/plugins/save/plugin.min.js new file mode 100644 index 0000000..07fcb1b --- /dev/null +++ b/web/resource/components/tinymce/plugins/save/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("save",function(e){function a(){var a;return a=tinymce.DOM.getParent(e.id,"form"),!e.getParam("save_enablewhendirty",!0)||e.isDirty()?(tinymce.triggerSave(),e.getParam("save_onsavecallback")?void(e.execCallback("save_onsavecallback",e)&&(e.startContent=tinymce.trim(e.getContent({format:"raw"})),e.nodeChanged())):void(a?(e.isNotDirty=!0,(!a.onsubmit||a.onsubmit())&&("function"==typeof a.submit?a.submit():e.windowManager.alert("Error: Form submit field collision.")),e.nodeChanged()):e.windowManager.alert("Error: No form element found."))):void 0}function n(){var a=tinymce.trim(e.startContent);return e.getParam("save_oncancelcallback")?void e.execCallback("save_oncancelcallback",e):(e.setContent(a),e.undoManager.clear(),void e.nodeChanged())}function t(){var a=this;e.on("nodeChange",function(){a.disabled(e.getParam("save_enablewhendirty",!0)&&!e.isDirty())})}e.addCommand("mceSave",a),e.addCommand("mceCancel",n),e.addButton("save",{icon:"save",text:"Save",cmd:"mceSave",disabled:!0,onPostRender:t}),e.addButton("cancel",{text:"Cancel",icon:!1,cmd:"mceCancel",disabled:!0,onPostRender:t}),e.addShortcut("ctrl+s","","mceSave")}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/searchreplace/plugin.min.js b/web/resource/components/tinymce/plugins/searchreplace/plugin.min.js new file mode 100644 index 0000000..367c6bd --- /dev/null +++ b/web/resource/components/tinymce/plugins/searchreplace/plugin.min.js @@ -0,0 +1 @@ +!function(){function e(e,t,n,a,r){function i(e,t){if(t=t||0,!e[0])throw"findAndReplaceDOMText cannot handle zero-length matches";var n=e.index;if(t>0){var a=e[t];if(!a)throw"Invalid capture group";n+=e[0].indexOf(a),e[0]=a}return[n,n+e[0].length,[e[0]]]}function d(e){var t;if(3===e.nodeType)return e.data;if(h[e.nodeName]&&!u[e.nodeName])return"";if(t="",(u[e.nodeName]||m[e.nodeName])&&(t+="\n"),e=e.firstChild)do t+=d(e);while(e=e.nextSibling);return t}function o(e,t,n){var a,r,i,d,o=[],l=0,c=e,s=t.shift(),f=0;e:for(;;){if((u[c.nodeName]||m[c.nodeName])&&l++,3===c.nodeType&&(!r&&c.length+l>=s[1]?(r=c,d=s[1]-l):a&&o.push(c),!a&&c.length+l>s[0]&&(a=c,i=s[0]-l),l+=c.length),a&&r){if(c=n({startNode:a,startNodeIndex:i,endNode:r,endNodeIndex:d,innerNodes:o,match:s[2],matchIndex:f}),l-=r.length-d,a=null,r=null,o=[],s=t.shift(),f++,!s)break}else{if((!h[c.nodeName]||u[c.nodeName])&&c.firstChild){c=c.firstChild;continue}if(c.nextSibling){c=c.nextSibling;continue}}for(;;){if(c.nextSibling){c=c.nextSibling;break}if(c.parentNode===e)break e;c=c.parentNode}}}function l(e){var t;if("function"!=typeof e){var n=e.nodeType?e:f.createElement(e);t=function(e,t){var a=n.cloneNode(!1);return a.setAttribute("data-mce-index",t),e&&a.appendChild(f.createTextNode(e)),a}}else t=e;return function(e){var n,a,r,i=e.startNode,d=e.endNode,o=e.matchIndex;if(i===d){var l=i;r=l.parentNode,e.startNodeIndex>0&&(n=f.createTextNode(l.data.substring(0,e.startNodeIndex)),r.insertBefore(n,l));var c=t(e.match[0],o);return r.insertBefore(c,l),e.endNodeIndexh;++h){var g=e.innerNodes[h],p=t(g.data,o);g.parentNode.replaceChild(p,g),u.push(p)}var x=t(d.data.substring(0,e.endNodeIndex),o);return r=i.parentNode,r.insertBefore(n,i),r.insertBefore(s,i),r.removeChild(i),r=d.parentNode,r.insertBefore(x,d),r.insertBefore(a,d),r.removeChild(d),x}}var c,s,f,u,h,m,g=[],p=0;if(f=t.ownerDocument,u=r.getBlockElements(),h=r.getWhiteSpaceElements(),m=r.getShortEndedElements(),s=d(t)){if(e.global)for(;c=e.exec(s);)g.push(i(c,a));else c=s.match(e),g.push(i(c,a));return g.length&&(p=g.length,o(t,g,l(n))),p}}function t(t){function n(){function e(){r.statusbar.find("#next").disabled(!d(s+1).length),r.statusbar.find("#prev").disabled(!d(s-1).length)}function n(){tinymce.ui.MessageBox.alert("Could not find the specified string.",function(){r.find("#find")[0].focus()})}var a={},r=tinymce.ui.Factory.create({type:"window",layout:"flex",pack:"center",align:"center",onClose:function(){t.focus(),c.done()},onSubmit:function(t){var i,o,l,f;return t.preventDefault(),o=r.find("#case").checked(),f=r.find("#words").checked(),l=r.find("#find").value(),l.length?a.text==l&&a.caseState==o&&a.wholeWord==f?0===d(s+1).length?void n():(c.next(),void e()):(i=c.find(l,o,f),i||n(),r.statusbar.items().slice(1).disabled(0===i),e(),void(a={text:l,caseState:o,wholeWord:f})):(c.done(!1),void r.statusbar.items().slice(1).disabled(!0))},buttons:[{text:"Find",onclick:function(){r.submit()}},{text:"Replace",disabled:!0,onclick:function(){c.replace(r.find("#replace").value())||(r.statusbar.items().slice(1).disabled(!0),s=-1,a={})}},{text:"Replace all",disabled:!0,onclick:function(){c.replace(r.find("#replace").value(),!0,!0),r.statusbar.items().slice(1).disabled(!0),a={}}},{type:"spacer",flex:1},{text:"Prev",name:"prev",disabled:!0,onclick:function(){c.prev(),e()}},{text:"Next",name:"next",disabled:!0,onclick:function(){c.next(),e()}}],title:"Find and replace",items:{type:"form",padding:20,labelGap:30,spacing:10,items:[{type:"textbox",name:"find",size:40,label:"Find",value:t.selection.getNode().src},{type:"textbox",name:"replace",size:40,label:"Replace with"},{type:"checkbox",name:"case",text:"Match case",label:" "},{type:"checkbox",name:"words",text:"Whole words",label:" "}]}}).renderTo().reflow()}function a(e){var t=e.getAttribute("data-mce-index");return"number"==typeof t?""+t:t}function r(n){var a,r;return r=t.dom.create("span",{"data-mce-bogus":1}),r.className="mce-match-marker",a=t.getBody(),c.done(!1),e(n,a,r,!1,t.schema)}function i(e){var t=e.parentNode;e.firstChild&&t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function d(e){var n,r=[];if(n=tinymce.toArray(t.getBody().getElementsByTagName("span")),n.length)for(var i=0;is&&f[o].setAttribute("data-mce-index",m-1)}return t.undoManager.add(),s=p,n?(g=d(p+1).length>0,c.next()):(g=d(p-1).length>0,c.prev()),!r&&g},c.done=function(e){var n,r,d,o;for(r=tinymce.toArray(t.getBody().getElementsByTagName("span")),n=0;n=d.end?(o=s,a=d.end-l):r&&c.push(s),!r&&s.length+l>d.start&&(r=s,i=d.start-l),l+=s.length),r&&o){if(s=n({startNode:r,startNodeIndex:i,endNode:o,endNodeIndex:a,innerNodes:c,match:d.text,matchIndex:u}),l-=o.length-a,r=null,o=null,c=[],d=t.shift(),u++,!d)break}else{if((!T[s.nodeName]||S[s.nodeName])&&s.firstChild){s=s.firstChild;continue}if(s.nextSibling){s=s.nextSibling;continue}}for(;;){if(s.nextSibling){s=s.nextSibling;break}if(s.parentNode===e)break e;s=s.parentNode}}}function i(e){function t(t,n){var r=w[n];r.stencil||(r.stencil=e(r));var o=r.stencil.cloneNode(!1);return o.setAttribute("data-mce-index",n),t&&o.appendChild(b.doc.createTextNode(t)),o}return function(e){var n,r,o,i=e.startNode,a=e.endNode,c=e.matchIndex,l=b.doc;if(i===a){var s=i;o=s.parentNode,e.startNodeIndex>0&&(n=l.createTextNode(s.data.substring(0,e.startNodeIndex)),o.insertBefore(n,s));var d=t(e.match,c);return o.insertBefore(d,s),e.endNodeIndexh;++h){var m=e.innerNodes[h],p=t(m.data,c);m.parentNode.replaceChild(p,m),f.push(p)}var v=t(a.data.substring(0,e.endNodeIndex),c);return o=i.parentNode,o.insertBefore(n,i),o.insertBefore(u,i),o.removeChild(i),o=a.parentNode,o.insertBefore(v,a),o.insertBefore(r,a),o.removeChild(a),v}}function a(e){var t=e.parentNode;t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function c(t){var n=e.getElementsByTagName("*"),r=[];t="number"==typeof t?""+t:null;for(var o=0;ot&&e(w[t],t)!==!1;t++);return this}function u(t){return w.length&&o(e,w,i(t)),this}function f(e,t){if(y&&e.global)for(;k=e.exec(y);)w.push(n(k,t));return this}function h(e){var t,n=c(e?l(e):null);for(t=n.length;t--;)a(n[t]);return this}function g(e){return w[e.getAttribute("data-mce-index")]}function m(e){return c(l(e))[0]}function p(e,t,n){return w.push({start:e,end:e+t,text:y.substr(e,t),data:n}),this}function v(e){var n=c(l(e)),r=t.dom.createRng();return r.setStartBefore(n[0]),r.setEndAfter(n[n.length-1]),r}function x(e,n){var r=v(e);return r.deleteContents(),n.length>0&&r.insertNode(t.dom.doc.createTextNode(n)),r}function N(){return w.splice(0,w.length),h(),this}var k,w=[],y,b=t.dom,S,T,B;return S=t.schema.getBlockElements(),T=t.schema.getWhiteSpaceElements(),B=t.schema.getShortEndedElements(),y=r(e),{text:y,matches:w,each:d,filter:s,reset:N,matchFromElement:g,elementFromMatch:m,find:f,add:p,wrap:u,unwrap:h,replace:x,rangeFromMatch:v,indexOf:l}}}),r(s,[l,d,u,f,h,g,m,p],function(e,t,n,r,o,i,a,c){t.add("spellchecker",function(t,l){function s(){return T.textMatcher||(T.textMatcher=new e(t.getBody(),t)),T.textMatcher}function d(e,t){var r=[];return n.each(t,function(e){r.push({selectable:!0,text:e.name,data:e.value})}),r}function u(e){for(var t in e)return!1;return!0}function f(e,i){var a=[],c=B[e];n.each(c,function(e){a.push({text:e,onclick:function(){t.insertContent(t.dom.encode(e)),t.dom.remove(i),v()}})}),a.push({text:"-"}),E&&a.push({text:"Add to Dictionary",onclick:function(){x(e,i)}}),a.push.apply(a,[{text:"Ignore",onclick:function(){N(e,i)}},{text:"Ignore all",onclick:function(){N(e,i,!0)}},{text:"Finish",onclick:k}]),I=new r({items:a,context:"contextmenu",onautohide:function(e){-1!=e.target.className.indexOf("spellchecker")&&e.preventDefault()},onhide:function(){I.remove(),I=null}}),I.renderTo(document.body);var l=o.DOM.getPos(t.getContentAreaContainer()),s=t.dom.getPos(i[0]),d=t.dom.getRoot();"BODY"==d.nodeName?(s.x-=d.ownerDocument.documentElement.scrollLeft||d.scrollLeft,s.y-=d.ownerDocument.documentElement.scrollTop||d.scrollTop):(s.x-=d.scrollLeft,s.y-=d.scrollTop),l.x+=s.x,l.y+=s.y,I.moveTo(l.x,l.y+i[0].offsetHeight)}function h(){return t.getParam("spellchecker_wordchar_pattern")||new RegExp('[^\\s!"#$%&()*+,-./:;<=>?@[\\]^_{|}`\xa7\xa9\xab\xae\xb1\xb6\xb7\xb8\xbb\xbc\xbd\xbe\xbf\xd7\xf7\xa4\u201d\u201c\u201e]+',"g")}function g(e,t,r,o){var s={method:e},d="";"spellcheck"==e&&(s.text=t,s.lang=M.spellchecker_language),"addToDictionary"==e&&(s.word=t),n.each(s,function(e,t){d&&(d+="&"),d+=t+"="+encodeURIComponent(e)}),i.send({url:new a(l).toAbsolute(M.spellchecker_rpc_url),type:"post",content_type:"application/x-www-form-urlencoded",data:d,success:function(e){e=c.parse(e),e?e.error?o(e.error):r(e):o("Sever response wasn't proper JSON.")},error:function(e,t){o("Spellchecker request error: "+t.status)}})}function m(e,t,n,r){var o=M.spellchecker_callback||g;o.call(T,e,t,n,r)}function p(){function e(e){var n;return e.words?(E=!!e.dictionary,n=e.words):n=e,t.setProgressState(!1),u(n)?(t.windowManager.alert("No misspellings found"),void(C=!1)):(B=n,s().find(h()).filter(function(e){return!!n[e.text]}).wrap(function(e){return t.dom.create("span",{"class":"mce-spellchecker-word","data-mce-bogus":1,"data-mce-word":e.text})}),void t.fire("SpellcheckStart"))}function n(e){t.windowManager.alert(e),t.setProgressState(!1),k()}return C?void k():(k(),C=!0,t.setProgressState(!0),m("spellcheck",s().text,e,n),void t.focus())}function v(){t.dom.select("span.mce-spellchecker-word").length||k()}function x(e,n){t.setProgressState(!0),m("addToDictionary",e,function(){t.setProgressState(!1),t.dom.remove(n,!0),v()},function(e){t.windowManager.alert(e),t.setProgressState(!1)})}function N(e,r,o){t.selection.collapse(),o?n.each(t.dom.select("span.mce-spellchecker-word"),function(n){n.getAttribute("data-mce-word")==e&&t.dom.remove(n,!0)}):t.dom.remove(r,!0),v()}function k(){s().reset(),T.textMatcher=null,C&&(C=!1,t.fire("SpellcheckEnd"))}function w(e){var t=e.getAttribute("data-mce-index");return"number"==typeof t?""+t:t}function y(e){var r,o=[];if(r=n.toArray(t.getBody().getElementsByTagName("span")),r.length)for(var i=0;i0){var o=t.dom.createRng();o.setStartBefore(r[0]),o.setEndAfter(r[r.length-1]),t.selection.setRng(o),f(n.getAttribute("data-mce-word"),r)}}}),t.addMenuItem("spellchecker",{text:"Spellcheck",context:"tools",onclick:p,selectable:!0,onPostRender:function(){var e=this;t.on("SpellcheckStart SpellcheckEnd",function(){e.active(C)})}});var _={tooltip:"Spellcheck",onclick:p,onPostRender:function(){var e=this;t.on("SpellcheckStart SpellcheckEnd",function(){e.active(C)})}};S.length>1&&(_.type="splitbutton",_.menu=S,_.onshow=b,_.onselect=function(e){M.spellchecker_language=e.control.settings.data}),t.addButton("spellchecker",_),t.addCommand("mceSpellCheck",p),t.on("remove",function(){I&&(I.remove(),I=null)}),t.on("change",v),this.getTextMatcher=s,this.getWordCharPattern=h,this.getLanguage=function(){return M.spellchecker_language},M.spellchecker_language=M.spellchecker_language||M.language||"en"})}),a([l,s])}(this); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/tabfocus/plugin.min.js b/web/resource/components/tinymce/plugins/tabfocus/plugin.min.js new file mode 100644 index 0000000..68fe35e --- /dev/null +++ b/web/resource/components/tinymce/plugins/tabfocus/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("tabfocus",function(e){function n(e){9!==e.keyCode||e.ctrlKey||e.altKey||e.metaKey||e.preventDefault()}function t(n){function t(n){function t(e){return"BODY"===e.nodeName||"hidden"!=e.type&&"none"!=e.style.display&&"hidden"!=e.style.visibility&&t(e.parentNode)}function r(e){return e.tabIndex||"INPUT"==e.nodeName||"TEXTAREA"==e.nodeName}function c(e){return!r(e)&&"-1"!=e.getAttribute("tabindex")&&t(e)}if(u=i.select(":input:enabled,*[tabindex]:not(iframe)"),o(u,function(n,t){return n.id==e.id?(a=t,!1):void 0}),n>0){for(d=a+1;d=0;d--)if(c(u[d]))return u[d];return null}var a,u,c,d;if(!(9!==n.keyCode||n.ctrlKey||n.altKey||n.metaKey)&&(c=r(e.getParam("tab_focus",e.getParam("tabfocus_elements",":prev,:next"))),1==c.length&&(c[1]=c[0],c[0]=":prev"),u=n.shiftKey?":prev"==c[0]?t(-1):i.get(c[0]):":next"==c[1]?t(1):i.get(c[1]))){var y=tinymce.get(u.id||u.name);u.id&&y?y.focus():window.setTimeout(function(){tinymce.Env.webkit||window.focus(),u.focus()},10),n.preventDefault()}}var i=tinymce.DOM,o=tinymce.each,r=tinymce.explode;e.on("init",function(){e.inline&&tinymce.DOM.setAttrib(e.getBody(),"tabIndex",null)}),e.on("keyup",n),tinymce.Env.gecko?e.on("keypress keydown",t):e.on("keydown",t)}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/table/plugin.min.js b/web/resource/components/tinymce/plugins/table/plugin.min.js new file mode 100644 index 0000000..4ee5cca --- /dev/null +++ b/web/resource/components/tinymce/plugins/table/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,o=[],a=0;a "+t+" tr",r);a(n,function(n,l){l+=e,a(H.select("> td, > th",n),function(e,n){var a,r,i,s;if(M[l])for(;M[l][n];)n++;for(i=o(e,"rowspan"),s=o(e,"colspan"),r=l;l+i>r;r++)for(M[r]||(M[r]=[]),a=n;n+s>a;a++)M[r][a]={part:t,real:r==l&&a==n,elm:e,rowspan:i,colspan:s};_=Math.max(_,n+1)})}),e+=n.length})}function s(e,t){return e=e.cloneNode(t),e.removeAttribute("id"),e}function c(e,t){var n;return n=M[t],n?n[e]:void 0}function d(e,t,n){e&&(n=parseInt(n,10),1===n?e.removeAttribute(t,1):e.setAttribute(t,n,1))}function u(e){return e&&(H.hasClass(e.elm,"mce-item-selected")||e==E)}function m(){var e=[];return a(r.rows,function(t){a(t.cells,function(n){return H.hasClass(n,"mce-item-selected")||E&&n==E.elm?(e.push(t),!1):void 0})}),e}function f(){var e=H.createRng();e.setStartAfter(r),e.setEndAfter(r),L.setRng(e),H.remove(r)}function g(t){var o,r={};return l.settings.table_clone_elements!==!1&&(r=e.makeMap((l.settings.table_clone_elements||"strong em b i span font h1 h2 h3 h4 h5 h6 p div").toUpperCase(),/[ ,]/)),e.walk(t,function(e){var l;return 3==e.nodeType?(a(H.getParents(e.parentNode,null,t).reverse(),function(e){r[e.nodeName]&&(e=s(e,!1),o?l&&l.appendChild(e):o=l=e,l=e)}),l&&(l.innerHTML=n.ie?" ":'
'),!1):void 0},"childNodes"),t=s(t,!1),d(t,"rowSpan",1),d(t,"colSpan",1),o?t.appendChild(o):(!n.ie||n.ie>10)&&(t.innerHTML='
'),t}function p(){var e=H.createRng(),t;return a(H.select("tr",r),function(e){0===e.cells.length&&H.remove(e)}),0===H.select("tr",r).length?(e.setStartBefore(r),e.setEndBefore(r),L.setRng(e),void H.remove(r)):(a(H.select("thead,tbody,tfoot",r),function(e){0===e.rows.length&&H.remove(e)}),i(),void(D&&(t=M[Math.min(M.length-1,D.y)],t&&(L.select(t[Math.min(t.length-1,D.x)].elm,!0),L.collapse(!0)))))}function h(e,t,n,o){var a,l,r,i,s;for(a=M[t][e].elm.parentNode,r=1;n>=r;r++)if(a=H.getNext(a,"tr")){for(l=e;l>=0;l--)if(s=M[t+r][l].elm,s.parentNode==a){for(i=1;o>=i;i++)H.insertAfter(g(s),s);break}if(-1==l)for(i=1;o>=i;i++)a.insertBefore(g(a.cells[0]),a.cells[0])}}function b(){a(M,function(e,t){a(e,function(e,n){var a,l,r;if(u(e)&&(e=e.elm,a=o(e,"colspan"),l=o(e,"rowspan"),a>1||l>1)){for(d(e,"rowSpan",1),d(e,"colSpan",1),r=0;a-1>r;r++)H.insertAfter(g(e),e);h(n,t,l-1,a)}})})}function v(t,n,o){var l,r,s,m,f,g,h,v,x,y,w;if(t?(l=T(t),r=l.x,s=l.y,m=r+(n-1),f=s+(o-1)):(D=I=null,a(M,function(e,t){a(e,function(e,n){u(e)&&(D||(D={x:n,y:t}),I={x:n,y:t})})}),D&&(r=D.x,s=D.y,m=I.x,f=I.y)),v=c(r,s),x=c(m,f),v&&x&&v.part==x.part){for(b(),i(),v=c(r,s).elm,d(v,"colSpan",m-r+1),d(v,"rowSpan",f-s+1),h=s;f>=h;h++)for(g=r;m>=g;g++)M[h]&&M[h][g]&&(t=M[h][g].elm,t!=v&&(y=e.grep(t.childNodes),a(y,function(e){v.appendChild(e)}),y.length&&(y=e.grep(v.childNodes),w=0,a(y,function(e){"BR"==e.nodeName&&H.getAttrib(e,"data-mce-bogus")&&w++0&&M[n-1][i]&&(p=M[n-1][i].elm,h=o(p,"rowSpan"),h>1)){d(p,"rowSpan",h+1);continue}}else if(h=o(l,"rowspan"),h>1){d(l,"rowSpan",h+1);continue}f=g(l),d(f,"colSpan",l.colSpan),m.appendChild(f),r=l}m.hasChildNodes()&&(e?c.parentNode.insertBefore(m,c):H.insertAfter(m,c))}}function y(e){var t,n;a(M,function(n){return a(n,function(n,o){return u(n)&&(t=o,e)?!1:void 0}),e?!t:void 0}),a(M,function(a,l){var r,i,s;a[t]&&(r=a[t].elm,r!=n&&(s=o(r,"colspan"),i=o(r,"rowspan"),1==s?e?(r.parentNode.insertBefore(g(r),r),h(t,l,i-1,s)):(H.insertAfter(g(r),r),h(t,l,i-1,s)):d(r,"colSpan",r.colSpan+1),n=r))})}function w(){var t=[];a(M,function(n){a(n,function(n,l){u(n)&&-1===e.inArray(t,l)&&(a(M,function(e){var t=e[l].elm,n;n=o(t,"colSpan"),n>1?d(t,"colSpan",n-1):H.remove(t)}),t.push(l))})}),p()}function C(){function e(e){var t,n;a(e.cells,function(e){var n=o(e,"rowSpan");n>1&&(d(e,"rowSpan",n-1),t=T(e),h(t.x,t.y,1,1))}),t=T(e.cells[0]),a(M[t.y],function(e){var t;e=e.elm,e!=n&&(t=o(e,"rowSpan"),1>=t?H.remove(e):d(e,"rowSpan",t-1),n=e)})}var t;t=m(),a(t.reverse(),function(t){e(t)}),p()}function R(){var e=m();return H.remove(e),p(),e}function N(){var e=m();return a(e,function(t,n){e[n]=s(t,!0)}),e}function S(e,t){var n=m(),o=n[t?0:n.length-1],l=o.cells.length;e&&(a(M,function(e){var t;return l=0,a(e,function(e){e.real&&(l+=e.colspan),e.elm.parentNode==o&&(t=1)}),t?!1:void 0}),t||e.reverse(),a(e,function(e){var n,a=e.cells.length,r;for(n=0;a>n;n++)r=e.cells[n],d(r,"colSpan",1),d(r,"rowSpan",1);for(n=a;l>n;n++)e.appendChild(g(e.cells[a-1]));for(n=l;a>n;n++)H.remove(e.cells[n]);t?o.parentNode.insertBefore(e,o):H.insertAfter(e,o)}),H.removeClass(H.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"))}function T(e){var t;return a(M,function(n,o){return a(n,function(n,a){return n.elm==e?(t={x:a,y:o},!1):void 0}),!t}),t}function P(e){D=T(e)}function A(){var e,t;return e=t=0,a(M,function(n,o){a(n,function(n,a){var l,r;u(n)&&(n=M[o][a],a>e&&(e=a),o>t&&(t=o),n.real&&(l=n.colspan-1,r=n.rowspan-1,l&&a+l>e&&(e=a+l),r&&o+r>t&&(t=o+r)))})}),{x:e,y:t}}function k(e){var t,n,o,a,l,r,i,s,c,d;if(I=T(e),D&&I){for(t=Math.min(D.x,I.x),n=Math.min(D.y,I.y),o=Math.max(D.x,I.x),a=Math.max(D.y,I.y),l=o,r=a,d=n;r>=d;d++)e=M[d][t],e.real||t-(e.colspan-1)=c;c++)e=M[n][c],e.real||n-(e.rowspan-1)=d;d++)for(c=t;o>=c;c++)e=M[d][c],e.real&&(i=e.colspan-1,s=e.rowspan-1,i&&c+i>l&&(l=c+i),s&&d+s>r&&(r=d+s));for(H.removeClass(H.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=n;r>=d;d++)for(c=t;l>=c;c++)M[d][c]&&H.addClass(M[d][c].elm,"mce-item-selected")}}function B(e,t){var n,o,a;n=T(e),o=n.y*_+n.x;do{if(o+=t,a=c(o%_,Math.floor(o/_)),!a)break;if(a.elm!=e)return L.select(a.elm,!0),H.isEmpty(a.elm)&&L.collapse(!0),!0}while(a.elm==e);return!1}var M,_,D,I,E,L=l.selection,H=L.dom;r=r||H.getParent(L.getStart(),"table"),i(),E=H.getParent(L.getStart(),"th,td"),E&&(D=T(E),I=A(),E=c(D.x,D.y)),e.extend(this,{deleteTable:f,split:b,merge:v,insertRow:x,insertCol:y,deleteCols:w,deleteRows:C,cutRows:R,copyRows:N,pasteRows:S,getPos:T,setStartCell:P,setEndCell:k,moveRelIdx:B,refresh:i})}}),o(u,[m,d,c],function(e,t,n){function o(e,t){return parseInt(e.getAttribute(t)||1,10)}var a=n.each;return function(n){function l(){function t(t){function l(e,o){var a=e?"previousSibling":"nextSibling",l=n.dom.getParent(o,"tr"),i=l[a];if(i)return h(n,o,i,e),t.preventDefault(),!0;var d=n.dom.getParent(l,"table"),u=l.parentNode,m=u.nodeName.toLowerCase();if("tbody"===m||m===(e?"tfoot":"thead")){var f=r(e,d,u,"tbody");if(null!==f)return s(e,f,o)}return c(e,l,a,d)}function r(e,t,o,a){var l=n.dom.select(">"+a,t),r=l.indexOf(o);if(e&&0===r||!e&&r===l.length-1)return i(e,t);if(-1===r){var s="thead"===o.tagName.toLowerCase()?0:l.length-1;return l[s]}return l[r+(e?-1:1)]}function i(e,t){var o=e?"thead":"tfoot",a=n.dom.select(">"+o,t);return 0!==a.length?a[0]:null}function s(e,o,a){var l=d(o,e);return l&&h(n,a,l,e),t.preventDefault(),!0}function c(e,o,a,r){var i=r[a];if(i)return u(i),!0;var s=n.dom.getParent(r,"td,th");if(s)return l(e,s,t);var c=d(o,!e);return u(c),t.preventDefault(),!1}function d(e,t){var o=e&&e[t?"lastChild":"firstChild"];return o&&"BR"===o.nodeName?n.dom.getParent(o,"td,th"):o}function u(e){n.selection.setCursorLocation(e,0)}function m(){return x==e.UP||x==e.DOWN}function f(e){var t=e.selection.getNode(),n=e.dom.getParent(t,"tr");return null!==n}function g(e){for(var t=0,n=e;n.previousSibling;)n=n.previousSibling,t+=o(n,"colspan");return t}function p(e,t){var n=0,l=0;return a(e.children,function(e,a){return n+=o(e,"colspan"),l=a,n>t?!1:void 0}),l}function h(e,t,o,a){var l=g(n.dom.getParent(t,"td,th")),r=p(o,l),i=o.childNodes[r],s=d(i,a);u(s||i)}function b(e){var t=n.selection.getNode(),o=n.dom.getParent(t,"td,th"),a=n.dom.getParent(e,"td,th");return o&&o!==a&&v(o,a)}function v(e,t){return n.dom.getParent(e,"TABLE")===n.dom.getParent(t,"TABLE")}var x=t.keyCode;if(m()&&f(n)){var y=n.selection.getNode();setTimeout(function(){b(y)&&l(!t.shiftKey&&x===e.UP,y,t)},0)}}n.on("KeyDown",function(e){t(e)})}function r(){function e(e,t){var n=t.ownerDocument,o=n.createRange(),a;return o.setStartBefore(t),o.setEnd(e.endContainer,e.endOffset),a=n.createElement("body"),a.appendChild(o.cloneContents()),0===a.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length}n.on("KeyDown",function(t){var o,a,l=n.dom;(37==t.keyCode||38==t.keyCode)&&(o=n.selection.getRng(),a=l.getParent(o.startContainer,"table"),a&&n.getBody().firstChild==a&&e(o,a)&&(o=l.createRng(),o.setStartBefore(a),o.setEndBefore(a),n.selection.setRng(o),t.preventDefault()))})}function i(){n.on("KeyDown SetContent VisualAid",function(){var e;for(e=n.getBody().lastChild;e;e=e.previousSibling)if(3==e.nodeType){if(e.nodeValue.length>0)break}else if(1==e.nodeType&&("BR"==e.tagName||!e.getAttribute("data-mce-bogus")))break;e&&"TABLE"==e.nodeName&&(n.settings.forced_root_block?n.dom.add(n.getBody(),n.settings.forced_root_block,n.settings.forced_root_block_attrs,t.ie&&t.ie<11?" ":'
'):n.dom.add(n.getBody(),"br",{"data-mce-bogus":"1"}))}),n.on("PreProcess",function(e){var t=e.node.lastChild;t&&("BR"==t.nodeName||1==t.childNodes.length&&("BR"==t.firstChild.nodeName||"\xa0"==t.firstChild.nodeValue))&&t.previousSibling&&"TABLE"==t.previousSibling.nodeName&&n.dom.remove(t)})}function s(){function e(e,t,n,o){var a=3,l=e.dom.getParent(t.startContainer,"TABLE"),r,i,s;return l&&(r=l.parentNode),i=t.startContainer.nodeType==a&&0===t.startOffset&&0===t.endOffset&&o&&("TR"==n.nodeName||n==r),s=("TD"==n.nodeName||"TH"==n.nodeName)&&!o,i||s}function t(){var t=n.selection.getRng(),o=n.selection.getNode(),a=n.dom.getParent(t.startContainer,"TD,TH");if(e(n,t,o,a)){a||(a=o);for(var l=a.lastChild;l.lastChild;)l=l.lastChild;3==l.nodeType&&(t.setEnd(l,l.data.length),n.selection.setRng(t))}}n.on("KeyDown",function(){t()}),n.on("MouseDown",function(e){2!=e.button&&t()})}function c(){n.on("keydown",function(t){if((t.keyCode==e.DELETE||t.keyCode==e.BACKSPACE)&&!t.isDefaultPrevented()){var o=n.dom.getParent(n.selection.getStart(),"table");if(o){for(var a=n.dom.select("td,th",o),l=a.length;l--;)if(!n.dom.hasClass(a[l],"mce-item-selected"))return;t.preventDefault(),n.execCommand("mceTableDelete")}}})}c(),t.webkit&&(l(),s()),t.gecko&&(r(),i()),t.ie>10&&(r(),i())}}),o(f,[s,g,c],function(e,t,n){return function(o){function a(){o.getBody().style.webkitUserSelect="",d&&(o.dom.removeClass(o.dom.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=!1)}function l(t){var n,a,l=t.target;if(s&&(i||l!=s)&&("TD"==l.nodeName||"TH"==l.nodeName)){a=r.getParent(l,"table"),a==c&&(i||(i=new e(o,a),i.setStartCell(s),o.getBody().style.webkitUserSelect="none"),i.setEndCell(l),d=!0),n=o.selection.getSel();try{n.removeAllRanges?n.removeAllRanges():n.empty()}catch(u){}t.preventDefault()}}var r=o.dom,i,s,c,d=!0;return o.on("MouseDown",function(e){2!=e.button&&(a(),s=r.getParent(e.target,"td,th"),c=r.getParent(s,"table"))}),o.on("mouseover",l),o.on("remove",function(){r.unbind(o.getDoc(),"mouseover",l)}),o.on("MouseUp",function(){function e(e,o){var l=new t(e,e);do{if(3==e.nodeType&&0!==n.trim(e.nodeValue).length)return void(o?a.setStart(e,0):a.setEnd(e,e.nodeValue.length));if("BR"==e.nodeName)return void(o?a.setStartBefore(e):a.setEndBefore(e))}while(e=o?l.next():l.prev())}var a,l=o.selection,d,u,m,f;if(s){if(i&&(o.getBody().style.webkitUserSelect=""),d=r.select("td.mce-item-selected,th.mce-item-selected"),d.length>0){a=r.createRng(),m=d[0],a.setStartBefore(m),a.setEndAfter(m),e(m,1),u=new t(m,r.getParent(d[0],"table"));do if("TD"==m.nodeName||"TH"==m.nodeName){if(!r.hasClass(m,"mce-item-selected"))break;f=m}while(m=u.next());e(f),l.setRng(a)}o.nodeChanged(),s=i=c=null}}),o.on("KeyUp Drop",function(){a(),s=i=c=null}),{clear:a}}}),o(p,[s,u,f,c,g,d,h],function(e,t,n,o,a,l,r){function i(a){function r(e){return e?e.replace(/px$/,""):""}function i(e){return/^[0-9]+$/.test(e)&&(e+="px"),e}function c(e){s("left center right".split(" "),function(t){a.formatter.remove("align"+t,{},e)})}function d(e){s("top middle bottom".split(" "),function(t){a.formatter.remove("valign"+t,{},e)})}function u(e,t){return o.each(t,function(t){t.textStyle=function(){return a.formatter.getCssText({block:e,classes:[t.value]})}}),t}function m(e,t,n,l){var r,i=[];return o.each(a.settings[t]||l,function(t){var o={text:t.text||t.title,value:t.value};i.push(o),(e[n]===t.value||!r&&t.selected)&&(r=o)}),r&&(e[n]=r.value,r.selected=!0),i}function f(){var e=a.dom,t,n,d,f,g;t=e.getParent(a.selection.getStart(),"table"),g={width:r(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:r(e.getStyle(t,"height")||e.getAttrib(t,"height")),cellspacing:t?e.getAttrib(t,"cellspacing"):"",cellpadding:t?e.getAttrib(t,"cellpadding"):"",border:t?e.getAttrib(t,"border"):"",caption:!!e.select("caption",t)[0],"class":e.getAttrib(t,"class")},s("left center right".split(" "),function(e){a.formatter.matchNode(t,"align"+e)&&(g.align=e)}),t||(n={label:"Cols",name:"cols"},d={label:"Rows",name:"rows"}),a.settings.table_class_list&&(g["class"]&&(g["class"]=g["class"].replace(/\s*mce\-item\-table\s*/g,"")),f={name:"class",type:"listbox",label:"Class",values:u("table",m(g,"table_class_list","class"))}),a.windowManager.open({title:"Table properties",items:{type:"form",layout:"flex",direction:"column",labelGapCalc:"children",items:[{type:"form",labelGapCalc:!1,padding:0,layout:"grid",columns:2,data:g,defaults:{type:"textbox",maxWidth:50},items:[n,d,{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell spacing",name:"cellspacing"},{label:"Cell padding",name:"cellpadding"},{label:"Border",name:"border"},{label:"Caption",name:"caption",type:"checkbox"}]},{label:"Alignment",name:"align",type:"listbox",text:"None",values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},f]},onsubmit:function(){var n;g=o.extend(g,this.toJSON()),a.undoManager.transact(function(){t||(t=v(g.cols||1,g.rows||1)),a.dom.setAttribs(t,{cellspacing:g.cellspacing,cellpadding:g.cellpadding,border:g.border,"class":g["class"]}),a.dom.setStyles(t,{width:i(g.width),height:i(g.height)}),n=e.select("caption",t)[0],n&&!g.caption&&e.remove(n),!n&&g.caption&&(n=e.create("caption"),n.innerHTML=l.ie?"\xa0":'
',t.insertBefore(n,t.firstChild)),c(t),g.align&&a.formatter.apply("align"+g.align,{},t),a.focus(),a.addVisual()})}})}function g(e,t){a.windowManager.open({title:"Merge cells",body:[{label:"Cols",name:"cols",type:"textbox",value:"1",size:10},{label:"Rows",name:"rows",type:"textbox",value:"1",size:10}],onsubmit:function(){var n=this.toJSON();a.undoManager.transact(function(){e.merge(t,n.cols,n.rows)})}})}function p(){var e=a.dom,t,n,l,f=[];f=a.dom.select("td.mce-item-selected,th.mce-item-selected"),t=a.dom.getParent(a.selection.getStart(),"td,th"),!f.length&&t&&f.push(t),t=t||f[0],t&&(n={width:r(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:r(e.getStyle(t,"height")||e.getAttrib(t,"height")),scope:e.getAttrib(t,"scope"),"class":e.getAttrib(t,"class")},n.type=t.nodeName.toLowerCase(),s("left center right".split(" "),function(e){a.formatter.matchNode(t,"align"+e)&&(n.align=e)}),s("top middle bottom".split(" "),function(e){a.formatter.matchNode(t,"valign"+e)&&(n.valign=e)}),a.settings.table_cell_class_list&&(l={name:"class",type:"listbox",label:"Class",values:u("td",m(n,"table_cell_class_list","class"))}),a.windowManager.open({title:"Cell properties",items:{type:"form",layout:"flex",direction:"column",labelGapCalc:"children",items:[{type:"form",data:n,layout:"grid",columns:2,labelGapCalc:!1,padding:0,defaults:{type:"textbox",maxWidth:50},items:[{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell type",name:"type",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"Cell",value:"td"},{text:"Header cell",value:"th"}]},{label:"Scope",name:"scope",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Row",value:"row"},{text:"Column",value:"col"},{text:"Row group",value:"rowgroup"},{text:"Column group",value:"colgroup"}]},{label:"H Align",name:"align",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"V Align",name:"valign",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Top",value:"top"},{text:"Middle",value:"middle"},{text:"Bottom",value:"bottom"}]}]},l]},onsubmit:function(){n=o.extend(n,this.toJSON()),a.undoManager.transact(function(){s(f,function(t){a.dom.setAttribs(t,{scope:n.scope,"class":n["class"]}),a.dom.setStyles(t,{width:i(n.width),height:i(n.height)}),n.type&&t.nodeName.toLowerCase()!=n.type&&(t=e.rename(t,n.type)),c(t),n.align&&a.formatter.apply("align"+n.align,{},t),d(t),n.valign&&a.formatter.apply("valign"+n.valign,{},t)}),a.focus()})}}))}function h(){var e=a.dom,t,n,l,d,f,g=[];t=a.dom.getParent(a.selection.getStart(),"table"),n=a.dom.getParent(a.selection.getStart(),"td,th"),s(t.rows,function(t){s(t.cells,function(o){return e.hasClass(o,"mce-item-selected")||o==n?(g.push(t),!1):void 0})}),l=g[0],l&&(f={height:r(e.getStyle(l,"height")||e.getAttrib(l,"height")),scope:e.getAttrib(l,"scope"),"class":e.getAttrib(l,"class")},f.type=l.parentNode.nodeName.toLowerCase(),s("left center right".split(" "),function(e){a.formatter.matchNode(l,"align"+e)&&(f.align=e)}),a.settings.table_row_class_list&&(d={name:"class",type:"listbox",label:"Class",values:u("tr",m(f,"table_row_class_list","class"))}),a.windowManager.open({title:"Row properties",items:{type:"form",data:f,columns:2,defaults:{type:"textbox"},items:[{type:"listbox",name:"type",label:"Row type",text:"None",maxWidth:null,values:[{text:"Header",value:"thead"},{text:"Body",value:"tbody"},{text:"Footer",value:"tfoot"}]},{type:"listbox",name:"align",label:"Alignment",text:"None",maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"Height",name:"height"},d]},onsubmit:function(){var t,n,l;f=o.extend(f,this.toJSON()),a.undoManager.transact(function(){var o=f.type;s(g,function(r){a.dom.setAttribs(r,{scope:f.scope,"class":f["class"]}),a.dom.setStyles(r,{height:i(f.height)}),o!=r.parentNode.nodeName.toLowerCase()&&(t=e.getParent(r,"table"),n=r.parentNode,l=e.select(o,t)[0],l||(l=e.create(o),t.firstChild?t.insertBefore(l,t.firstChild):t.appendChild(l)),l.appendChild(r),n.hasChildNodes()||e.remove(n)),c(r),f.align&&a.formatter.apply("align"+f.align,{},r)}),a.focus()})}}))}function b(e){return function(){a.execCommand(e)}}function v(e,t){var n,o,r;for(r='',n=0;t>n;n++){for(r+="",o=0;e>o;o++)r+="";r+=""}r+="
"+(l.ie?" ":"
")+"
",a.insertContent(r);var i=a.dom.get("__mce");return a.dom.setAttrib(i,"id",null),a.dom.setAttribs(i,a.settings.table_default_attributes||{}),a.dom.setStyles(i,a.settings.table_default_styles||{}),i}function x(e,t){function n(){e.disabled(!a.dom.getParent(a.selection.getStart(),t)),a.selection.selectorChanged(t,function(t){e.disabled(!t)})}a.initialized?n():a.on("init",n)}function y(){x(this,"table")}function w(){x(this,"td,th")}function C(){var e="";e='';for(var t=0;10>t;t++){e+="";for(var n=0;10>n;n++)e+='';e+=""}return e+="
",e+=''}function R(e,t,n){var o=n.getEl().getElementsByTagName("table")[0],l,r,i,s,c,d=n.isRtl()||"tl-tr"==n.parent().rel;for(o.nextSibling.innerHTML=e+1+" x "+(t+1),d&&(e=9-e),r=0;10>r;r++)for(l=0;10>l;l++)s=o.rows[r].childNodes[l].firstChild,c=(d?l>=e:e>=l)&&t>=r,a.dom.toggleClass(s,"mce-active",c),c&&(i=s);return i.parentNode}var N,S=this;a.settings.table_grid===!1?a.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",onclick:f}):a.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",ariaHideMenu:!0,onclick:function(e){e.aria&&(this.parent().hideAll(),e.stopImmediatePropagation(),f())},onshow:function(){R(0,0,this.menu.items()[0])},onhide:function(){var e=this.menu.items()[0].getEl().getElementsByTagName("a");a.dom.removeClass(e,"mce-active"),a.dom.addClass(e[0],"mce-active")},menu:[{type:"container",html:C(),onPostRender:function(){this.lastX=this.lastY=0},onmousemove:function(e){var t=e.target,n,o;"A"==t.tagName.toUpperCase()&&(n=parseInt(t.getAttribute("data-mce-x"),10),o=parseInt(t.getAttribute("data-mce-y"),10),(this.isRtl()||"tl-tr"==this.parent().rel)&&(n=9-n),(n!==this.lastX||o!==this.lastY)&&(R(n,o,e.control),this.lastX=n,this.lastY=o))},onkeydown:function(e){var t=this.lastX,n=this.lastY,o;switch(e.keyCode){case 37:t>0&&(t--,o=!0);break;case 39:o=!0,9>t&&t++;break;case 38:o=!0,n>0&&n--;break;case 40:o=!0,9>n&&n++}o&&(e.preventDefault(),e.stopPropagation(),R(t,n,e.control).focus(),this.lastX=t,this.lastY=n)},onclick:function(e){var t=this;"A"==e.target.tagName.toUpperCase()&&(e.preventDefault(),e.stopPropagation(),t.parent().cancel(),a.undoManager.transact(function(){v(t.lastX+1,t.lastY+1)}),a.addVisual())}}]}),a.addMenuItem("tableprops",{text:"Table properties",context:"table",onPostRender:y,onclick:f}),a.addMenuItem("deletetable",{text:"Delete table",context:"table",onPostRender:y,cmd:"mceTableDelete"}),a.addMenuItem("cell",{separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:b("mceTableCellProps"),onPostRender:w},{text:"Merge cells",onclick:b("mceTableMergeCells"),onPostRender:w},{text:"Split cell",onclick:b("mceTableSplitCells"),onPostRender:w}]}),a.addMenuItem("row",{text:"Row",context:"table",menu:[{text:"Insert row before",onclick:b("mceTableInsertRowBefore"),onPostRender:w},{text:"Insert row after",onclick:b("mceTableInsertRowAfter"),onPostRender:w},{text:"Delete row",onclick:b("mceTableDeleteRow"),onPostRender:w},{text:"Row properties",onclick:b("mceTableRowProps"),onPostRender:w},{text:"-"},{text:"Cut row",onclick:b("mceTableCutRow"),onPostRender:w},{text:"Copy row",onclick:b("mceTableCopyRow"),onPostRender:w},{text:"Paste row before",onclick:b("mceTablePasteRowBefore"),onPostRender:w},{text:"Paste row after",onclick:b("mceTablePasteRowAfter"),onPostRender:w}]}),a.addMenuItem("column",{text:"Column",context:"table",menu:[{text:"Insert column before",onclick:b("mceTableInsertColBefore"),onPostRender:w},{text:"Insert column after",onclick:b("mceTableInsertColAfter"),onPostRender:w},{text:"Delete column",onclick:b("mceTableDeleteCol"),onPostRender:w}]});var T=[];s("inserttable tableprops deletetable | cell row column".split(" "),function(e){T.push("|"==e?{text:"-"}:a.menuItems[e])}),a.addButton("table",{type:"menubutton",title:"Table",menu:T}),l.isIE||a.on("click",function(e){e=e.target,"TABLE"===e.nodeName&&(a.selection.select(e),a.nodeChanged())}),S.quirks=new t(a),a.on("Init",function(){S.cellSelection=new n(a)}),s({mceTableSplitCells:function(e){e.split()},mceTableMergeCells:function(e){var t;t=a.dom.getParent(a.selection.getStart(),"th,td"),a.dom.select("td.mce-item-selected,th.mce-item-selected").length?e.merge():g(e,t)},mceTableInsertRowBefore:function(e){e.insertRow(!0)},mceTableInsertRowAfter:function(e){e.insertRow()},mceTableInsertColBefore:function(e){e.insertCol(!0)},mceTableInsertColAfter:function(e){e.insertCol()},mceTableDeleteCol:function(e){e.deleteCols()},mceTableDeleteRow:function(e){e.deleteRows()},mceTableCutRow:function(e){N=e.cutRows()},mceTableCopyRow:function(e){N=e.copyRows()},mceTablePasteRowBefore:function(e){e.pasteRows(N,!0)},mceTablePasteRowAfter:function(e){e.pasteRows(N)},mceTableDelete:function(e){e.deleteTable()}},function(t,n){a.addCommand(n,function(){var n=new e(a);n&&(t(n),a.execCommand("mceRepaint"),S.cellSelection.clear())})}),s({mceInsertTable:function(){f()},mceTableRowProps:h,mceTableCellProps:p},function(e,t){a.addCommand(t,function(t,n){e(n)})}),a.settings.table_tab_navigation!==!1&&a.on("keydown",function(t){var n,o,l;9==t.keyCode&&(n=a.dom.getParent(a.selection.getStart(),"th,td"),n&&(t.preventDefault(),o=new e(a),l=t.shiftKey?-1:1,a.undoManager.transact(function(){!o.moveRelIdx(n,l)&&l>0&&(o.insertRow(),o.refresh(),o.moveRelIdx(n,l))})))})}var s=o.each;r.add("table",i)}),r([])}(this); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/template/plugin.min.js b/web/resource/components/tinymce/plugins/template/plugin.min.js new file mode 100644 index 0000000..cee38af --- /dev/null +++ b/web/resource/components/tinymce/plugins/template/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("template",function(e){function t(t){return function(){var a=e.settings.templates;"string"==typeof a?tinymce.util.XHR.send({url:a,success:function(e){t(tinymce.util.JSON.parse(e))}}):t(a)}}function a(t){function a(t){function a(t){if(-1==t.indexOf("")){var a="";tinymce.each(e.contentCSS,function(t){a+=''}),t=""+a+""+t+""}t=r(t,"template_preview_replace_values");var l=n.find("iframe")[0].getEl().contentWindow.document;l.open(),l.write(t),l.close()}var c=t.control.value();c.url?tinymce.util.XHR.send({url:c.url,success:function(e){l=e,a(l)}}):(l=c.content,a(l)),n.find("#description")[0].text(t.control.value().description)}var n,l,i=[];return t&&0!==t.length?(tinymce.each(t,function(e){i.push({selected:!i.length,text:e.title,value:{url:e.url,content:e.content,description:e.description}})}),n=e.windowManager.open({title:"Insert template",layout:"flex",direction:"column",align:"stretch",padding:15,spacing:10,items:[{type:"form",flex:0,padding:0,items:[{type:"container",label:"Templates",items:{type:"listbox",label:"Templates",name:"template",values:i,onselect:a}}]},{type:"label",name:"description",label:"Description",text:" "},{type:"iframe",flex:1,border:1}],onsubmit:function(){c(!1,l)},width:e.getParam("template_popup_width",600),height:e.getParam("template_popup_height",500)}),void n.find("listbox")[0].fire("select")):void e.windowManager.alert("No templates defined")}function n(t,a){function n(e,t){if(e=""+e,e.length0&&(o=p.create("div",null),o.appendChild(s[0].cloneNode(!0))),i(p.select("*",o),function(t){c(t,e.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_cdate_format",e.getLang("template.cdate_format")))),c(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format")))),c(t,e.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))&&(t.innerHTML=m)}),l(o),e.execCommand("mceInsertContent",!1,o.innerHTML),e.addVisual()}var i=tinymce.each;e.addCommand("mceInsertTemplate",c),e.addButton("template",{title:"Insert template",onclick:t(a)}),e.addMenuItem("template",{text:"Insert template",onclick:t(a),context:"insert"}),e.on("PreProcess",function(t){var a=e.dom;i(a.select("div",t.node),function(t){a.hasClass(t,"mceTmpl")&&(i(a.select("*",t),function(t){a.hasClass(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format"))))}),l(t))})})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/textcolor/plugin.min.js b/web/resource/components/tinymce/plugins/textcolor/plugin.min.js new file mode 100644 index 0000000..a42de76 --- /dev/null +++ b/web/resource/components/tinymce/plugins/textcolor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("textcolor",function(e){function t(){var t,o,l=[];for(o=e.settings.textcolor_map||["000000","Black","993300","Burnt orange","333300","Dark olive","003300","Dark green","003366","Dark azure","000080","Navy Blue","333399","Indigo","333333","Very dark gray","800000","Maroon","FF6600","Orange","808000","Olive","008000","Green","008080","Teal","0000FF","Blue","666699","Grayish blue","808080","Gray","FF0000","Red","FF9900","Amber","99CC00","Yellow green","339966","Sea green","33CCCC","Turquoise","3366FF","Royal blue","800080","Purple","999999","Medium gray","FF00FF","Magenta","FFCC00","Gold","FFFF00","Yellow","00FF00","Lime","00FFFF","Aqua","00CCFF","Sky blue","993366","Red violet","C0C0C0","Silver","FF99CC","Pink","FFCC99","Peach","FFFF99","Light yellow","CCFFCC","Pale green","CCFFFF","Pale cyan","99CCFF","Light sky blue","CC99FF","Plum","FFFFFF","White"],t=0;t',a=o.length-1,c=e.settings.textcolor_rows||5,i=e.settings.textcolor_cols||8,F=0;c>F;F++){for(r+="",n=0;i>n;n++)d=F*i+n,d>a?r+="":(l=o[d],r+='
');r+=""}return r+=""}function l(t){var o,l=this.parent();(o=t.target.getAttribute("data-mce-color"))&&(this.lastId&&document.getElementById(this.lastId).setAttribute("aria-selected",!1),t.target.setAttribute("aria-selected",!0),this.lastId=t.target.id,l.hidePanel(),o="#"+o,l.color(o),e.execCommand(l.settings.selectcmd,!1,o))}function r(){var t=this;t._color&&e.execCommand(t.settings.selectcmd,!1,t._color)}e.addButton("forecolor",{type:"colorbutton",tooltip:"Text color",selectcmd:"ForeColor",panel:{role:"application",ariaRemember:!0,html:o,onclick:l},onclick:r}),e.addButton("backcolor",{type:"colorbutton",tooltip:"Background color",selectcmd:"HiliteColor",panel:{role:"application",ariaRemember:!0,html:o,onclick:l},onclick:r})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/visualblocks/plugin.min.js b/web/resource/components/tinymce/plugins/visualblocks/plugin.min.js new file mode 100644 index 0000000..8c48ed0 --- /dev/null +++ b/web/resource/components/tinymce/plugins/visualblocks/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("visualblocks",function(e,s){function o(){var s=this;s.active(a),e.on("VisualBlocks",function(){s.active(e.dom.hasClass(e.getBody(),"mce-visualblocks"))})}var l,t,a;window.NodeList&&(e.addCommand("mceVisualBlocks",function(){var o,c=e.dom;l||(l=c.uniqueId(),o=c.create("link",{id:l,rel:"stylesheet",href:s+"/css/visualblocks.css"}),e.getDoc().getElementsByTagName("head")[0].appendChild(o)),e.on("PreviewFormats AfterPreviewFormats",function(s){a&&c.toggleClass(e.getBody(),"mce-visualblocks","afterpreviewformats"==s.type)}),c.toggleClass(e.getBody(),"mce-visualblocks"),a=e.dom.hasClass(e.getBody(),"mce-visualblocks"),t&&t.active(c.hasClass(e.getBody(),"mce-visualblocks")),e.fire("VisualBlocks")}),e.addButton("visualblocks",{title:"Show blocks",cmd:"mceVisualBlocks",onPostRender:o}),e.addMenuItem("visualblocks",{text:"Show blocks",cmd:"mceVisualBlocks",onPostRender:o,selectable:!0,context:"view",prependToContext:!0}),e.on("init",function(){e.settings.visualblocks_default_state&&e.execCommand("mceVisualBlocks",!1,null,{skip_focus:!0})}),e.on("remove",function(){e.dom.removeClass(e.getBody(),"mce-visualblocks")}))}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/visualchars/plugin.min.js b/web/resource/components/tinymce/plugins/visualchars/plugin.min.js new file mode 100644 index 0000000..fc7e109 --- /dev/null +++ b/web/resource/components/tinymce/plugins/visualchars/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("visualchars",function(e){function a(a){var t,s,i,r,c,d,l=e.getBody(),m=e.selection;if(n=!n,o.state=n,e.fire("VisualChars",{state:n}),a&&(d=m.getBookmark()),n)for(s=[],tinymce.walk(l,function(e){3==e.nodeType&&e.nodeValue&&-1!=e.nodeValue.indexOf(" ")&&s.push(e)},"childNodes"),i=0;i$1'),c=e.dom.create("div",null,r);t=c.lastChild;)e.dom.insertAfter(t,s[i]);e.dom.remove(s[i])}else for(s=e.dom.select("span.mce-nbsp",l),i=s.length-1;i>=0;i--)e.dom.remove(s[i],1);m.moveToBookmark(d)}function t(){var a=this;e.on("VisualChars",function(e){a.active(e.state)})}var n,o=this;e.addCommand("mceVisualChars",a),e.addButton("visualchars",{title:"Show invisible characters",cmd:"mceVisualChars",onPostRender:t}),e.addMenuItem("visualchars",{text:"Show invisible characters",cmd:"mceVisualChars",onPostRender:t,selectable:!0,context:"view",prependToContext:!0}),e.on("beforegetcontent",function(e){n&&"raw"!=e.format&&!e.draft&&(n=!0,a(!1))})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/wordcount/plugin.min.js b/web/resource/components/tinymce/plugins/wordcount/plugin.min.js new file mode 100644 index 0000000..c5f1788 --- /dev/null +++ b/web/resource/components/tinymce/plugins/wordcount/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("wordcount",function(a){function b(){a.theme.panel.find("#wordcount").text(["Words: {0}",e.getCount()])}var c,d,e=this;c=a.getParam("wordcount_countregex",/[\w\u2019\x27\-\u00C0-\u1FFF]+/g),h=a.getParam("wordhcount_countregex",/[\u2E80-\u9FFF]{1}/g),d=a.getParam("wordcount_cleanregex",/[.(),;:!?%#$?\x27\x22_+=\\\/\-]*/g),a.on("init",function(){var c=a.theme.panel&&a.theme.panel.find("#statusbar")[0];c&&window.setTimeout(function(){c.insert({type:"label",name:"wordcount",text:["Words: {0}",e.getCount()],classes:"wordcount",disabled:a.settings.readonly},0),a.on("setcontent beforeaddundo",b),a.on("keyup",function(a){32==a.keyCode&&b()})},0)}),e.getCount=function(){var b=a.getContent({format:"raw"}),e=0;if(b){b=b.replace(/\.\.\./g," "),b=b.replace(/<.[^<>]*?>/g," "),b=b.replace(/ | /gi," "),b=b.replace(/(\w+)(&#?[a-z0-9]+;)+(\w+)/i,"$1$3"),b=b.replace(/&.+?;/g," "),b=b.replace(d,"");var f=b.match(c);f&&(e=f.length);var g=b.match(h);g&&(e+=g.length)}return e}}); \ No newline at end of file diff --git a/web/resource/components/tinymce/skins/lightgray/fonts/readme.md b/web/resource/components/tinymce/skins/lightgray/fonts/readme.md new file mode 100644 index 0000000..fa5d639 --- /dev/null +++ b/web/resource/components/tinymce/skins/lightgray/fonts/readme.md @@ -0,0 +1 @@ +Icons are generated and provided by the http://icomoon.io service. diff --git a/web/resource/components/tinymce/skins/lightgray/img/object.gif b/web/resource/components/tinymce/skins/lightgray/img/object.gif new file mode 100644 index 0000000..cccd7f0 Binary files /dev/null and b/web/resource/components/tinymce/skins/lightgray/img/object.gif differ diff --git a/web/resource/components/ueditor/dialogs/attachment/images/progress.png b/web/resource/components/ueditor/dialogs/attachment/images/progress.png new file mode 100644 index 0000000..717c486 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/attachment/images/progress.png differ diff --git a/web/resource/components/ueditor/dialogs/emotion/images/neweditor-tab-bg.png b/web/resource/components/ueditor/dialogs/emotion/images/neweditor-tab-bg.png new file mode 100644 index 0000000..8f398b0 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/emotion/images/neweditor-tab-bg.png differ diff --git a/web/resource/components/ueditor/dialogs/image/images/progress.png b/web/resource/components/ueditor/dialogs/image/images/progress.png new file mode 100644 index 0000000..717c486 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/image/images/progress.png differ diff --git a/web/resource/components/ueditor/dialogs/music/music.css b/web/resource/components/ueditor/dialogs/music/music.css new file mode 100644 index 0000000..b2c6136 --- /dev/null +++ b/web/resource/components/ueditor/dialogs/music/music.css @@ -0,0 +1 @@ +.listPanel,.page,.resultBar{overflow:hidden}.m-h,.pageon{font-weight:700}.wrapper{margin:5px 10px}.searchBar{height:30px;padding:7px 0 3px;text-align:center}.searchBtn{font-size:13px;height:24px}.resultBar{width:460px;margin:5px auto;border:1px solid #CCC;border-radius:5px;box-shadow:2px 2px 5px #D3D6DA}.panelon{display:block}.paneloff{display:none}.page{width:220px;margin:20px auto}.pageoff,.pageon{float:right;width:24px;line-height:24px;height:24px;margin-right:5px;text-align:center}.pageon{background:0 0;border:none;color:#000}.pageoff{cursor:pointer;background-color:#fff;border:1px solid #E7ECF0;color:#2D64B3;text-decoration:none}.m-l,.m-m,.m-s,.m-t,.m-try-t,.m-z{float:left}.m-box{width:460px}.m-m{line-height:20px;height:20px}.m-h{height:24px;line-height:24px;padding-left:46px;background-color:#FAFAFA;border-bottom:1px solid #DAD8D8;font-size:12px;color:#333}.m-l{width:40px}.m-t{width:140px}.m-s{width:110px}.m-z{width:100px}.m-try-t{width:60px}.m-try,.m-trying{float:left;width:20px;height:20px}.m-try{background:url(http://static.tieba.baidu.com/tb/editor/images/try_music.gif) no-repeat}.m-trying{background:url(http://static.tieba.baidu.com/tb/editor/images/stop_music.gif) no-repeat}.loading{width:95px;height:7px;font-size:7px;margin:60px auto;background:url(http://static.tieba.baidu.com/tb/editor/images/loading.gif) no-repeat}.empty{width:300px;height:40px;padding:2px;margin:50px auto;line-height:40px;color:#069;text-align:center} \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/music/music.html b/web/resource/components/ueditor/dialogs/music/music.html new file mode 100644 index 0000000..e7ef04f --- /dev/null +++ b/web/resource/components/ueditor/dialogs/music/music.html @@ -0,0 +1,32 @@ + + + + + 插入音乐 + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/music/music.js b/web/resource/components/ueditor/dialogs/music/music.js new file mode 100644 index 0000000..1c538bf --- /dev/null +++ b/web/resource/components/ueditor/dialogs/music/music.js @@ -0,0 +1,192 @@ +function Music() { + this.init(); +} +(function () { + var pages = [], + panels = [], + selectedItem = null; + Music.prototype = { + total:70, + pageSize:10, + dataUrl:"http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.common", + playerUrl:"http://box.baidu.com/widget/flash/bdspacesong.swf", + + init:function () { + var me = this; + domUtils.on($G("J_searchName"), "keyup", function (event) { + var e = window.event || event; + if (e.keyCode == 13) { + me.dosearch(); + } + }); + domUtils.on($G("J_searchBtn"), "click", function () { + me.dosearch(); + }); + }, + callback:function (data) { + var me = this; + me.data = data.song_list; + setTimeout(function () { + $G('J_resultBar').innerHTML = me._renderTemplate(data.song_list); + }, 300); + }, + dosearch:function () { + var me = this; + selectedItem = null; + var key = $G('J_searchName').value; + if (utils.trim(key) == "")return false; + key = encodeURIComponent(key); + me._sent(key); + }, + doselect:function (i) { + var me = this; + if (typeof i == 'object') { + selectedItem = i; + } else if (typeof i == 'number') { + selectedItem = me.data[i]; + } + }, + onpageclick:function (id) { + var me = this; + for (var i = 0; i < pages.length; i++) { + $G(pages[i]).className = 'pageoff'; + $G(panels[i]).className = 'paneloff'; + } + $G('page' + id).className = 'pageon'; + $G('panel' + id).className = 'panelon'; + }, + listenTest:function (elem) { + var me = this, + view = $G('J_preview'), + is_play_action = (elem.className == 'm-try'), + old_trying = me._getTryingElem(); + + if (old_trying) { + old_trying.className = 'm-try'; + view.innerHTML = ''; + } + if (is_play_action) { + elem.className = 'm-trying'; + view.innerHTML = me._buildMusicHtml(me._getUrl(true)); + } + }, + _sent:function (param) { + var me = this; + $G('J_resultBar').innerHTML = '
'; + + utils.loadFile(document, { + src:me.dataUrl + '&query=' + param + '&page_size=' + me.total + '&callback=music.callback&.r=' + Math.random(), + tag:"script", + type:"text/javascript", + defer:"defer" + }); + }, + _removeHtml:function (str) { + var reg = /<\s*\/?\s*[^>]*\s*>/gi; + return str.replace(reg, ""); + }, + _getUrl:function (isTryListen) { + var me = this; + var param = 'from=tiebasongwidget&url=&name=' + encodeURIComponent(me._removeHtml(selectedItem.title)) + '&artist=' + + encodeURIComponent(me._removeHtml(selectedItem.author)) + '&extra=' + + encodeURIComponent(me._removeHtml(selectedItem.album_title)) + + '&autoPlay='+isTryListen+'' + '&loop=true'; + return me.playerUrl + "?" + param; + }, + _getTryingElem:function () { + var s = $G('J_listPanel').getElementsByTagName('span'); + + for (var i = 0; i < s.length; i++) { + if (s[i].className == 'm-trying') + return s[i]; + } + return null; + }, + _buildMusicHtml:function (playerUrl) { + var html = ' 12) + return s.substring(0, 5) + '...'; + if (!s) s = " "; + return s; + }, + _rebuildData:function (data) { + var me = this, + newData = [], + d = me.pageSize, + itembox; + for (var i = 0; i < data.length; i++) { + if ((i + d) % d == 0) { + itembox = []; + newData.push(itembox) + } + itembox.push(data[i]); + } + return newData; + }, + _renderTemplate:function (data) { + var me = this; + if (data.length == 0)return '
' + lang.emptyTxt + '
'; + data = me._rebuildData(data); + var s = [], p = [], t = []; + s.push('
'); + p.push('
'); + for (var i = 0, tmpList; tmpList = data[i++];) { + panels.push('panel' + i); + pages.push('page' + i); + if (i == 1) { + s.push('
'); + if (data.length != 1) { + t.push('
' + (i ) + '
'); + } + } else { + s.push('
'); + t.push('
' + (i ) + '
'); + } + s.push('
'); + s.push('
' + lang.chapter + '' + lang.singer + + '' + lang.special + '' + lang.listenTest + '
'); + for (var j = 0, tmpObj; tmpObj = tmpList[j++];) { + s.push(''); + } + s.push('
'); + s.push('
'); + } + t.reverse(); + p.push(t.join('')); + s.push('
'); + p.push('
'); + return s.join('') + p.join(''); + }, + exec:function () { + var me = this; + if (selectedItem == null) return; + $G('J_preview').innerHTML = ""; + editor.execCommand('music', { + url:me._getUrl(false), + width:400, + height:95 + }); + } + }; +})(); + + + diff --git a/web/resource/components/ueditor/dialogs/preview/preview.html b/web/resource/components/ueditor/dialogs/preview/preview.html new file mode 100644 index 0000000..f6b433b --- /dev/null +++ b/web/resource/components/ueditor/dialogs/preview/preview.html @@ -0,0 +1,40 @@ + + + + + + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/scrawl/images/redo.png b/web/resource/components/ueditor/dialogs/scrawl/images/redo.png new file mode 100644 index 0000000..12cd9bb Binary files /dev/null and b/web/resource/components/ueditor/dialogs/scrawl/images/redo.png differ diff --git a/web/resource/components/ueditor/dialogs/scrawl/images/redoH.png b/web/resource/components/ueditor/dialogs/scrawl/images/redoH.png new file mode 100644 index 0000000..d9f33d3 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/scrawl/images/redoH.png differ diff --git a/web/resource/components/ueditor/dialogs/template/images/pre0.png b/web/resource/components/ueditor/dialogs/template/images/pre0.png new file mode 100644 index 0000000..8f3c16a Binary files /dev/null and b/web/resource/components/ueditor/dialogs/template/images/pre0.png differ diff --git a/web/resource/components/ueditor/dialogs/template/images/pre1.png b/web/resource/components/ueditor/dialogs/template/images/pre1.png new file mode 100644 index 0000000..5a03f96 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/template/images/pre1.png differ diff --git a/web/resource/components/ueditor/dialogs/template/images/pre2.png b/web/resource/components/ueditor/dialogs/template/images/pre2.png new file mode 100644 index 0000000..5a55672 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/template/images/pre2.png differ diff --git a/web/resource/components/ueditor/dialogs/template/images/pre3.png b/web/resource/components/ueditor/dialogs/template/images/pre3.png new file mode 100644 index 0000000..d852d29 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/template/images/pre3.png differ diff --git a/web/resource/components/ueditor/dialogs/template/images/pre4.png b/web/resource/components/ueditor/dialogs/template/images/pre4.png new file mode 100644 index 0000000..0d7bc72 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/template/images/pre4.png differ diff --git a/web/resource/components/ueditor/dialogs/video/images/none_focus.jpg b/web/resource/components/ueditor/dialogs/video/images/none_focus.jpg new file mode 100644 index 0000000..7c768dc Binary files /dev/null and b/web/resource/components/ueditor/dialogs/video/images/none_focus.jpg differ diff --git a/web/resource/components/ueditor/dialogs/video/images/progress.png b/web/resource/components/ueditor/dialogs/video/images/progress.png new file mode 100644 index 0000000..717c486 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/video/images/progress.png differ diff --git a/web/resource/components/ueditor/lang/en/images/music.png b/web/resource/components/ueditor/lang/en/images/music.png new file mode 100644 index 0000000..2f495fe Binary files /dev/null and b/web/resource/components/ueditor/lang/en/images/music.png differ diff --git a/web/resource/components/ueditor/lang/zh-cn/images/music.png b/web/resource/components/ueditor/lang/zh-cn/images/music.png new file mode 100644 index 0000000..354edeb Binary files /dev/null and b/web/resource/components/ueditor/lang/zh-cn/images/music.png differ diff --git a/web/resource/components/ueditor/themes/default/images/neweditor-tab-bg.png b/web/resource/components/ueditor/themes/default/images/neweditor-tab-bg.png new file mode 100644 index 0000000..8f398b0 Binary files /dev/null and b/web/resource/components/ueditor/themes/default/images/neweditor-tab-bg.png differ diff --git a/web/resource/components/ueditor/themes/default/images/pagebreak.gif b/web/resource/components/ueditor/themes/default/images/pagebreak.gif new file mode 100644 index 0000000..8d1cffd Binary files /dev/null and b/web/resource/components/ueditor/themes/default/images/pagebreak.gif differ diff --git a/web/resource/components/ueditor/third-party/highcharts/adapters/prototype-adapter.js b/web/resource/components/ueditor/third-party/highcharts/adapters/prototype-adapter.js new file mode 100644 index 0000000..8a57cca --- /dev/null +++ b/web/resource/components/ueditor/third-party/highcharts/adapters/prototype-adapter.js @@ -0,0 +1,15 @@ +/* + Highcharts JS v3.0.6 (2013-10-04) + Prototype adapter + + @author Michael Nelson, Torstein Hønsi. + + Feel free to use and modify this script. + Highcharts license: www.highcharts.com/license. +*/ +var HighchartsAdapter=function(){var f=typeof Effect!=="undefined";return{init:function(a){if(f)Effect.HighchartsTransition=Class.create(Effect.Base,{initialize:function(b,c,d,g){var e;this.element=b;this.key=c;e=b.attr?b.attr(c):$(b).getStyle(c);if(c==="d")this.paths=a.init(b,b.d,d),this.toD=d,e=0,d=1;this.start(Object.extend(g||{},{from:e,to:d,attribute:c}))},setup:function(){HighchartsAdapter._extend(this.element);if(!this.element._highchart_animation)this.element._highchart_animation={};this.element._highchart_animation[this.key]= +this},update:function(b){var c=this.paths,d=this.element;c&&(b=a.step(c[0],c[1],b,this.toD));d.attr?d.element&&d.attr(this.options.attribute,b):(c={},c[this.options.attribute]=b,$(d).setStyle(c))},finish:function(){this.element&&this.element._highchart_animation&&delete this.element._highchart_animation[this.key]}})},adapterRun:function(a,b){return parseInt($(a).getStyle(b),10)},getScript:function(a,b){var c=$$("head")[0];c&&c.appendChild((new Element("script",{type:"text/javascript",src:a})).observe("load", +b))},addNS:function(a){var b=/^(?:click|mouse(?:down|up|over|move|out))$/;return/^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/.test(a)||b.test(a)?a:"h:"+a},addEvent:function(a,b,c){a.addEventListener||a.attachEvent?Event.observe($(a),HighchartsAdapter.addNS(b),c):(HighchartsAdapter._extend(a),a._highcharts_observe(b,c))},animate:function(a,b,c){var d,c=c||{};c.delay=0;c.duration=(c.duration||500)/1E3;c.afterFinish=c.complete;if(f)for(d in b)new Effect.HighchartsTransition($(a), +d,b[d],c);else{if(a.attr)for(d in b)a.attr(d,b[d]);c.complete&&c.complete()}a.attr||$(a).setStyle(b)},stop:function(a){var b;if(a._highcharts_extended&&a._highchart_animation)for(b in a._highchart_animation)a._highchart_animation[b].cancel()},each:function(a,b){$A(a).each(b)},inArray:function(a,b,c){return b?b.indexOf(a,c):-1},offset:function(a){return $(a).cumulativeOffset()},fireEvent:function(a,b,c,d){a.fire?a.fire(HighchartsAdapter.addNS(b),c):a._highcharts_extended&&(c=c||{},a._highcharts_fire(b, +c));c&&c.defaultPrevented&&(d=null);d&&d(c)},removeEvent:function(a,b,c){$(a).stopObserving&&(b&&(b=HighchartsAdapter.addNS(b)),$(a).stopObserving(b,c));window===a?Event.stopObserving(a,b,c):(HighchartsAdapter._extend(a),a._highcharts_stop_observing(b,c))},washMouseEvent:function(a){return a},grep:function(a,b){return a.findAll(b)},map:function(a,b){return a.map(b)},_extend:function(a){a._highcharts_extended||Object.extend(a,{_highchart_events:{},_highchart_animation:null,_highcharts_extended:!0, +_highcharts_observe:function(b,a){this._highchart_events[b]=[this._highchart_events[b],a].compact().flatten()},_highcharts_stop_observing:function(b,a){b?a?this._highchart_events[b]=[this._highchart_events[b]].compact().flatten().without(a):delete this._highchart_events[b]:this._highchart_events={}},_highcharts_fire:function(a,c){var d=this;(this._highchart_events[a]||[]).each(function(a){if(!c.stopped)c.preventDefault=function(){c.defaultPrevented=!0},c.target=d,a.bind(this)(c)===!1&&c.preventDefault()}.bind(this))}})}}}(); diff --git a/web/resource/components/ueditor/third-party/highcharts/adapters/prototype-adapter.src.js b/web/resource/components/ueditor/third-party/highcharts/adapters/prototype-adapter.src.js new file mode 100644 index 0000000..9c8529e --- /dev/null +++ b/web/resource/components/ueditor/third-party/highcharts/adapters/prototype-adapter.src.js @@ -0,0 +1,316 @@ +/** + * @license Highcharts JS v3.0.6 (2013-10-04) + * Prototype adapter + * + * @author Michael Nelson, Torstein Hønsi. + * + * Feel free to use and modify this script. + * Highcharts license: www.highcharts.com/license. + */ + +// JSLint options: +/*global Effect, Class, Event, Element, $, $$, $A */ + +// Adapter interface between prototype and the Highcharts charting library +var HighchartsAdapter = (function () { + +var hasEffect = typeof Effect !== 'undefined'; + +return { + + /** + * Initialize the adapter. This is run once as Highcharts is first run. + * @param {Object} pathAnim The helper object to do animations across adapters. + */ + init: function (pathAnim) { + if (hasEffect) { + /** + * Animation for Highcharts SVG element wrappers only + * @param {Object} element + * @param {Object} attribute + * @param {Object} to + * @param {Object} options + */ + Effect.HighchartsTransition = Class.create(Effect.Base, { + initialize: function (element, attr, to, options) { + var from, + opts; + + this.element = element; + this.key = attr; + from = element.attr ? element.attr(attr) : $(element).getStyle(attr); + + // special treatment for paths + if (attr === 'd') { + this.paths = pathAnim.init( + element, + element.d, + to + ); + this.toD = to; + + + // fake values in order to read relative position as a float in update + from = 0; + to = 1; + } + + opts = Object.extend((options || {}), { + from: from, + to: to, + attribute: attr + }); + this.start(opts); + }, + setup: function () { + HighchartsAdapter._extend(this.element); + // If this is the first animation on this object, create the _highcharts_animation helper that + // contain pointers to the animation objects. + if (!this.element._highchart_animation) { + this.element._highchart_animation = {}; + } + + // Store a reference to this animation instance. + this.element._highchart_animation[this.key] = this; + }, + update: function (position) { + var paths = this.paths, + element = this.element, + obj; + + if (paths) { + position = pathAnim.step(paths[0], paths[1], position, this.toD); + } + + if (element.attr) { // SVGElement + + if (element.element) { // If not, it has been destroyed (#1405) + element.attr(this.options.attribute, position); + } + + } else { // HTML, #409 + obj = {}; + obj[this.options.attribute] = position; + $(element).setStyle(obj); + } + + }, + finish: function () { + // Delete the property that holds this animation now that it is finished. + // Both canceled animations and complete ones gets a 'finish' call. + if (this.element && this.element._highchart_animation) { // #1405 + delete this.element._highchart_animation[this.key]; + } + } + }); + } + }, + + /** + * Run a general method on the framework, following jQuery syntax + * @param {Object} el The HTML element + * @param {String} method Which method to run on the wrapped element + */ + adapterRun: function (el, method) { + + // This currently works for getting inner width and height. If adding + // more methods later, we need a conditional implementation for each. + return parseInt($(el).getStyle(method), 10); + + }, + + /** + * Downloads a script and executes a callback when done. + * @param {String} scriptLocation + * @param {Function} callback + */ + getScript: function (scriptLocation, callback) { + var head = $$('head')[0]; // Returns an array, so pick the first element. + if (head) { + // Append a new 'script' element, set its type and src attributes, add a 'load' handler that calls the callback + head.appendChild(new Element('script', { type: 'text/javascript', src: scriptLocation}).observe('load', callback)); + } + }, + + /** + * Custom events in prototype needs to be namespaced. This method adds a namespace 'h:' in front of + * events that are not recognized as native. + */ + addNS: function (eventName) { + var HTMLEvents = /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/, + MouseEvents = /^(?:click|mouse(?:down|up|over|move|out))$/; + return (HTMLEvents.test(eventName) || MouseEvents.test(eventName)) ? + eventName : + 'h:' + eventName; + }, + + // el needs an event to be attached. el is not necessarily a dom element + addEvent: function (el, event, fn) { + if (el.addEventListener || el.attachEvent) { + Event.observe($(el), HighchartsAdapter.addNS(event), fn); + + } else { + HighchartsAdapter._extend(el); + el._highcharts_observe(event, fn); + } + }, + + // motion makes things pretty. use it if effects is loaded, if not... still get to the end result. + animate: function (el, params, options) { + var key, + fx; + + // default options + options = options || {}; + options.delay = 0; + options.duration = (options.duration || 500) / 1000; + options.afterFinish = options.complete; + + // animate wrappers and DOM elements + if (hasEffect) { + for (key in params) { + // The fx variable is seemingly thrown away here, but the Effect.setup will add itself to the _highcharts_animation object + // on the element itself so its not really lost. + fx = new Effect.HighchartsTransition($(el), key, params[key], options); + } + } else { + if (el.attr) { // #409 without effects + for (key in params) { + el.attr(key, params[key]); + } + } + if (options.complete) { + options.complete(); + } + } + + if (!el.attr) { // HTML element, #409 + $(el).setStyle(params); + } + }, + + // this only occurs in higcharts 2.0+ + stop: function (el) { + var key; + if (el._highcharts_extended && el._highchart_animation) { + for (key in el._highchart_animation) { + // Cancel the animation + // The 'finish' function in the Effect object will remove the reference + el._highchart_animation[key].cancel(); + } + } + }, + + // um.. each + each: function (arr, fn) { + $A(arr).each(fn); + }, + + inArray: function (item, arr, from) { + return arr ? arr.indexOf(item, from) : -1; + }, + + /** + * Get the cumulative offset relative to the top left of the page. This method, unlike its + * jQuery and MooTools counterpart, still suffers from issue #208 regarding the position + * of a chart within a fixed container. + */ + offset: function (el) { + return $(el).cumulativeOffset(); + }, + + // fire an event based on an event name (event) and an object (el). + // again, el may not be a dom element + fireEvent: function (el, event, eventArguments, defaultFunction) { + if (el.fire) { + el.fire(HighchartsAdapter.addNS(event), eventArguments); + } else if (el._highcharts_extended) { + eventArguments = eventArguments || {}; + el._highcharts_fire(event, eventArguments); + } + + if (eventArguments && eventArguments.defaultPrevented) { + defaultFunction = null; + } + + if (defaultFunction) { + defaultFunction(eventArguments); + } + }, + + removeEvent: function (el, event, handler) { + if ($(el).stopObserving) { + if (event) { + event = HighchartsAdapter.addNS(event); + } + $(el).stopObserving(event, handler); + } if (window === el) { + Event.stopObserving(el, event, handler); + } else { + HighchartsAdapter._extend(el); + el._highcharts_stop_observing(event, handler); + } + }, + + washMouseEvent: function (e) { + return e; + }, + + // um, grep + grep: function (arr, fn) { + return arr.findAll(fn); + }, + + // um, map + map: function (arr, fn) { + return arr.map(fn); + }, + + // extend an object to handle highchart events (highchart objects, not svg elements). + // this is a very simple way of handling events but whatever, it works (i think) + _extend: function (object) { + if (!object._highcharts_extended) { + Object.extend(object, { + _highchart_events: {}, + _highchart_animation: null, + _highcharts_extended: true, + _highcharts_observe: function (name, fn) { + this._highchart_events[name] = [this._highchart_events[name], fn].compact().flatten(); + }, + _highcharts_stop_observing: function (name, fn) { + if (name) { + if (fn) { + this._highchart_events[name] = [this._highchart_events[name]].compact().flatten().without(fn); + } else { + delete this._highchart_events[name]; + } + } else { + this._highchart_events = {}; + } + }, + _highcharts_fire: function (name, args) { + var target = this; + (this._highchart_events[name] || []).each(function (fn) { + // args is never null here + if (args.stopped) { + return; // "throw $break" wasn't working. i think because of the scope of 'this'. + } + + // Attach a simple preventDefault function to skip default handler if called + args.preventDefault = function () { + args.defaultPrevented = true; + }; + args.target = target; + + // If the event handler return false, prevent the default handler from executing + if (fn.bind(this)(args) === false) { + args.preventDefault(); + } + } +.bind(this)); + } + }); + } + } +}; +}()); diff --git a/web/resource/components/ueditor/third-party/highcharts/modules/no-data-to-display.js b/web/resource/components/ueditor/third-party/highcharts/modules/no-data-to-display.js new file mode 100644 index 0000000..c9ff9ca --- /dev/null +++ b/web/resource/components/ueditor/third-party/highcharts/modules/no-data-to-display.js @@ -0,0 +1,12 @@ +/* + Highcharts JS v3.0.6 (2013-10-04) + Plugin for displaying a message when there is no data visible in chart. + + (c) 2010-2013 Highsoft AS + Author: Øystein Moseng + + License: www.highcharts.com/license +*/ +(function(c){function f(){return!!this.points.length}function g(){this.hasData()?this.hideNoData():this.showNoData()}var d=c.seriesTypes,e=c.Chart.prototype,h=c.getOptions(),i=c.extend;i(h.lang,{noData:"No data to display"});h.noData={position:{x:0,y:0,align:"center",verticalAlign:"middle"},attr:{},style:{fontWeight:"bold",fontSize:"12px",color:"#60606a"}};d.pie.prototype.hasData=f;if(d.gauge)d.gauge.prototype.hasData=f;if(d.waterfall)d.waterfall.prototype.hasData=f;c.Series.prototype.hasData=function(){return this.dataMax!== +void 0&&this.dataMin!==void 0};e.showNoData=function(a){var b=this.options,a=a||b.lang.noData,b=b.noData;if(!this.noDataLabel)this.noDataLabel=this.renderer.label(a,0,0,null,null,null,null,null,"no-data").attr(b.attr).css(b.style).add(),this.noDataLabel.align(i(this.noDataLabel.getBBox(),b.position),!1,"plotBox")};e.hideNoData=function(){if(this.noDataLabel)this.noDataLabel=this.noDataLabel.destroy()};e.hasData=function(){for(var a=this.series,b=a.length;b--;)if(a[b].hasData()&&!a[b].options.isInternal)return!0; +return!1};e.callbacks.push(function(a){c.addEvent(a,"load",g);c.addEvent(a,"redraw",g)})})(Highcharts); diff --git a/web/resource/components/ueditor/third-party/highcharts/modules/no-data-to-display.src.js b/web/resource/components/ueditor/third-party/highcharts/modules/no-data-to-display.src.js new file mode 100644 index 0000000..bc278a8 --- /dev/null +++ b/web/resource/components/ueditor/third-party/highcharts/modules/no-data-to-display.src.js @@ -0,0 +1,128 @@ +/** + * @license Highcharts JS v3.0.6 (2013-10-04) + * Plugin for displaying a message when there is no data visible in chart. + * + * (c) 2010-2013 Highsoft AS + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + */ + +(function (H) { // docs + + var seriesTypes = H.seriesTypes, + chartPrototype = H.Chart.prototype, + defaultOptions = H.getOptions(), + extend = H.extend; + + // Add language option + extend(defaultOptions.lang, { + noData: 'No data to display' + }); + + // Add default display options for message + defaultOptions.noData = { + position: { + x: 0, + y: 0, + align: 'center', + verticalAlign: 'middle' + }, + attr: { + }, + style: { + fontWeight: 'bold', + fontSize: '12px', + color: '#60606a' + } + }; + + /** + * Define hasData functions for series. These return true if there are data points on this series within the plot area + */ + function hasDataPie() { + return !!this.points.length; /* != 0 */ + } + + seriesTypes.pie.prototype.hasData = hasDataPie; + + if (seriesTypes.gauge) { + seriesTypes.gauge.prototype.hasData = hasDataPie; + } + + if (seriesTypes.waterfall) { + seriesTypes.waterfall.prototype.hasData = hasDataPie; + } + + H.Series.prototype.hasData = function () { + return this.dataMax !== undefined && this.dataMin !== undefined; + }; + + /** + * Display a no-data message. + * + * @param {String} str An optional message to show in place of the default one + */ + chartPrototype.showNoData = function (str) { + var chart = this, + options = chart.options, + text = str || options.lang.noData, + noDataOptions = options.noData; + + if (!chart.noDataLabel) { + chart.noDataLabel = chart.renderer.label(text, 0, 0, null, null, null, null, null, 'no-data') + .attr(noDataOptions.attr) + .css(noDataOptions.style) + .add(); + chart.noDataLabel.align(extend(chart.noDataLabel.getBBox(), noDataOptions.position), false, 'plotBox'); + } + }; + + /** + * Hide no-data message + */ + chartPrototype.hideNoData = function () { + var chart = this; + if (chart.noDataLabel) { + chart.noDataLabel = chart.noDataLabel.destroy(); + } + }; + + /** + * Returns true if there are data points within the plot area now + */ + chartPrototype.hasData = function () { + var chart = this, + series = chart.series, + i = series.length; + + while (i--) { + if (series[i].hasData() && !series[i].options.isInternal) { + return true; + } + } + + return false; + }; + + /** + * Show no-data message if there is no data in sight. Otherwise, hide it. + */ + function handleNoData() { + var chart = this; + if (chart.hasData()) { + chart.hideNoData(); + } else { + chart.showNoData(); + } + } + + /** + * Add event listener to handle automatic display of no-data message + */ + chartPrototype.callbacks.push(function (chart) { + H.addEvent(chart, 'load', handleNoData); + H.addEvent(chart, 'redraw', handleNoData); + }); + +}(Highcharts)); diff --git a/web/resource/components/webuploader/README.md b/web/resource/components/webuploader/README.md new file mode 100644 index 0000000..be468e3 --- /dev/null +++ b/web/resource/components/webuploader/README.md @@ -0,0 +1,26 @@ +目录说明 +======================== + +```bash +├── Uploader.swf # SWF文件,当使用Flash运行时需要引入。 +├ +├── webuploader.js # 完全版本。 +├── webuploader.min.js # min版本 +├ +├── webuploader.flashonly.js # 只有Flash实现的版本。 +├── webuploader.flashonly.min.js # min版本 +├ +├── webuploader.html5only.js # 只有Html5实现的版本。 +├── webuploader.html5only.min.js # min版本 +├ +├── webuploader.noimage.js # 去除图片处理的版本,包括HTML5和FLASH. +├── webuploader.noimage.min.js # min版本 +├ +├── webuploader.custom.js # 自定义打包方案,请查看 Gruntfile.js,满足移动端使用。 +└── webuploader.custom.min.js # min版本 +``` + +## 示例 + +请把整个 Git 包下载下来放在 php 服务器下,因为默认提供的文件接受是用 php 编写的,打开 examples 页面便能查看示例效果。 +version 0.1.5 \ No newline at end of file diff --git a/web/resource/components/webuploader/progress.png b/web/resource/components/webuploader/progress.png new file mode 100644 index 0000000..717c486 Binary files /dev/null and b/web/resource/components/webuploader/progress.png differ diff --git a/web/resource/images/msg-tab-z25df2d.png b/web/resource/images/msg-tab-z25df2d.png new file mode 100644 index 0000000..6a18531 Binary files /dev/null and b/web/resource/images/msg-tab-z25df2d.png differ diff --git a/web/resource/images/music-icon.png b/web/resource/images/music-icon.png new file mode 100644 index 0000000..135a2d4 Binary files /dev/null and b/web/resource/images/music-icon.png differ diff --git a/web/resource/images/noavatar_middle.gif b/web/resource/images/noavatar_middle.gif new file mode 100644 index 0000000..7016d11 Binary files /dev/null and b/web/resource/images/noavatar_middle.gif differ diff --git a/web/resource/images/nopic-107.png b/web/resource/images/nopic-107.png new file mode 100644 index 0000000..526f91e Binary files /dev/null and b/web/resource/images/nopic-107.png differ diff --git a/web/resource/images/nopic-203.png b/web/resource/images/nopic-203.png new file mode 100644 index 0000000..c05f229 Binary files /dev/null and b/web/resource/images/nopic-203.png differ diff --git a/web/resource/images/nopic-account.png b/web/resource/images/nopic-account.png new file mode 100644 index 0000000..443ea56 Binary files /dev/null and b/web/resource/images/nopic-account.png differ diff --git a/web/resource/images/nopic-module.png b/web/resource/images/nopic-module.png new file mode 100644 index 0000000..638efc9 Binary files /dev/null and b/web/resource/images/nopic-module.png differ diff --git a/web/resource/images/nopic-small.jpg b/web/resource/images/nopic-small.jpg new file mode 100644 index 0000000..26daf4f Binary files /dev/null and b/web/resource/images/nopic-small.jpg differ diff --git a/web/resource/images/nopic-template.png b/web/resource/images/nopic-template.png new file mode 100644 index 0000000..b913aa2 Binary files /dev/null and b/web/resource/images/nopic-template.png differ diff --git a/web/resource/images/nopic-user.png b/web/resource/images/nopic-user.png new file mode 100644 index 0000000..7e503b7 Binary files /dev/null and b/web/resource/images/nopic-user.png differ diff --git a/web/resource/images/nopic.jpg b/web/resource/images/nopic.jpg new file mode 100644 index 0000000..260fefc Binary files /dev/null and b/web/resource/images/nopic.jpg differ diff --git a/web/resource/images/nopic1.jpg b/web/resource/images/nopic1.jpg new file mode 100644 index 0000000..6d3c545 Binary files /dev/null and b/web/resource/images/nopic1.jpg differ diff --git a/web/resource/images/pen.png b/web/resource/images/pen.png new file mode 100644 index 0000000..f9fe360 Binary files /dev/null and b/web/resource/images/pen.png differ diff --git a/web/resource/images/player.jpg b/web/resource/images/player.jpg new file mode 100644 index 0000000..b98e110 Binary files /dev/null and b/web/resource/images/player.jpg differ diff --git a/web/resource/images/radio-icon.png b/web/resource/images/radio-icon.png new file mode 100644 index 0000000..5f19054 Binary files /dev/null and b/web/resource/images/radio-icon.png differ diff --git a/web/resource/js/app/order.min.js b/web/resource/js/app/order.min.js new file mode 100644 index 0000000..3e16af2 --- /dev/null +++ b/web/resource/js/app/order.min.js @@ -0,0 +1 @@ +define(["underscore","district","raty"],function(a,b){var c={editAdminRemark:function(a,b){},selectExpress:function(a,b){},editPayment:function(a,b){},adminClose:function(a,b){},send:function(a,b){},editAddress:function(a,b){},rank:function(a){}};return c.editAdminRemark=function(a,b){var c=$("#order-remark-container");return 0==c.length&&($(document.body).append(''),c=$("#order-remark-container")),$.get("./index.php?c=order&a=order&do=get_info",{id:a},function(d){if(console.log(d),d.errno)return void util.tips(d.message);var e=d,f=' ';c.html(f),c.find(".js-order-remark-post").off("click"),c.find(".js-order-remark-post").click(function(){var d=c.find('[name="admin_remark"]').val();$.post("./index.php?c=order&a=order&do=admin_remark",{id:a,admin_remark:d},function(a){console.log("admin-remark: ",a),a.errno?util.tips(a.message):(c.modal("hide"),$.isFunction(b)&&b(a),util.tips("订单修改备注操作成功!"))},"json")}),c.modal("show")},"json"),c},c.selectExpress=function(a,b){var c=$("#order-express-select-container");return 0==c.length&&($(document.body).append(''),c=$("#order-express-select-container")),$.get("./index.php?c=order&a=order&do=select_express",{id:a.id},function(d){if(d.errno)return void util.tips(d.message);var e=d,f=' ',c.html(f),c.find(".js-express-row").off("click"),c.find(".js-express-row").click(function(){$(this).find(":radio").get(0).checked=!0}),c.find(".js-express-submit").off("click"),c.find(".js-express-submit").on("click",function(){if(0==c.find("input[type='radio']:checked").length)return void util.tips("请选择快递公司.");var a=c.find("input[type='radio']:checked").parent().parent(),d={express:a.find(".js-express-cell").html(),post_fee:a.find(".js-fee-cell").html()};$.isFunction(b)&&b(d),c.modal("hide")}),c.modal("show")},"json"),c},c.editPayment=function(a,b){var d=$("#order-edit-payment-container");return 0==d.length&&($(document.body).append(''),d=$("#order-edit-payment-container")),d.empty(),$.get("./index.php?c=order&a=order&do=get_info",{id:a,items:!0},function(a){if(a.errno)return void util.tips(a.message);var e=a,f=' ';d.html(f),f=' 商品 单价/数量 小计(元) 涨价或减价 运费',$.each(e.items,function(a,b){f+='',f+=' ',f+='

'+b.name+"

"+b.specification+"

",f+='

¥'+b.price+"

x"+b.num+"

",f+=' ¥'+b.amount+"",1>a&&(f+='

 

',f+=' 免运费 | 选择快递'),f+=""}),$(".js-order-items").append(f);var g=0,h=function(){var a=$("input.js-order-post-fee").val(),b=$("input.js-order-adjust-fee").val(),c=parseFloat(e.total_fee),f=parseFloat(a),h=parseFloat(b);return g=f+h+c,0>f?($("input.js-order-post-fee").val("0.00"),valid=!1,void util.tips("快递费不能小于 0")):0>g?(valid=!1,g=0,h=0-c-f,$("input.js-order-adjust-fee").val(h),void util.tips("付款金额不能小于 0")):(d.find("span.js-order-post-fee").html(parseFloat(a).toFixed(2)),d.find("span.js-order-adjust-fee").html(parseFloat(h).toFixed(2)),void d.find("span.js-order-payment").html(parseFloat(g).toFixed(2)))};d.find(".js-post-fee-free").off("click"),d.find(".js-post-fee-free").on("click",function(){$("input.js-order-post-fee").val("0.00"),h()}),d.find(".js-order-fee").off("change"),d.find(".js-order-fee").change(function(){h()}),d.find(".js-order-select-express").off("change"),d.find(".js-order-select-express").click(function(){$modalobj=d,c.selectExpress(e,function(a){$modalobj.find("input.js-order-post-fee").val(parseFloat(a.post_fee).toFixed(2)),$modalobj.find('input[name="express"]').val(a.express),h()})}),d.find(".js-order-edit-payment-submit").off("click"),d.find(".js-order-edit-payment-submit").click(function(){!isNaN(g)&&g>=0?(postdata=util.serialize(d.find("input")),postdata.id=e.id,$.post("./index.php?c=order&a=order&do=edit_payment",postdata,function(a){a.errno?util.tips(a.message):($.isFunction(b)&&b(a),d.modal("hide"),util.tips("订单价格修改成功."))},"json")):util.tips("订单价格无法保存,请检查金额.")}),d.modal("show")},"json"),d},c.adminClose=function(a,b){var c=$("#order-cancel-container");if(0==c.length){var d='';$(document.body).append(d),c=$("#order-cancel-container")}c.find('input[name="cancel-reason"]').val(""),$.get("./index.php?c=order&a=order&do=get_info",{id:a},function(d){d.errno?util.tips(d.message):(c.find(".js-cancel-reason li a").off("click"),c.find(".js-cancel-reason li a").click(function(){var a=$(this).html();c.find('input[name="cancel-reason"]').val(a)}),c.find(".js-order-submit").off("click"),c.find(".js-order-submit").click(function(){var d=c.find('input[name="cancel-reason"]').val();null!=d&&d.length>0&&$.post("./index.php?c=order&a=order&do=admin_close",{id:a,cancel_reason:d},function(a){console.log(a),c.modal("hide"),a.errno?util.tips(a.message):($.isFunction(b)&&b(a),util.tips("取消订单成功."))},"json")}),c.find(".js-order-cancel").off("click"),c.find(".js-order-cancel").click(function(){c.modal("hide")}),c.modal("show"))},"json")},c.send=function(b,c){var d=$("#order-send-container");0==d.length&&($(document.body).append(''),d=$("#order-send-container")),$.get("./index.php?c=order&a=order&do=get_info",{id:b,items:!0,logistics:!0,exclude_refund:!0,present:!0},function(e){if(e.errno)util.tips(e.message);else{console.log(e);var f=e;for(var g in f.items)f.items[g].url=util.tomedia(f.items[g].thumb);var h="";h+='";var i='
';d.html(a.template(i)({order:f})),d.find(".js-order-send-cancel").off("click"),d.find(".js-order-send-cancel").click(function(){d.modal("hide")}),d.find(".js-order-send-submit").off("click"),d.find(".js-order-send-submit").click(function(){var a=d.find('input[name="express_no"]').val(),e=d.find('select[name="express"]').val();null!=a&&a.length>0?$.post("./index.php?c=order&a=order&do=send",{id:b,express_no:a,express:e},function(a){console.log(a),d.modal("hide"),a.errno?util.tips(a.message):($.isFunction(c)&&c(a),util.tips("订单发货成功."))},"json"):util.tips("快递单号不能为空")}),d.modal("show")}},"json")},c.editAddress=function(c,d){var e=$("#js-order-address-container");return 0==e.length&&($(document.body).append(''),e=$("#js-order-address-container")),$.get("./index.php?c=order&a=order&do=get_info",{id:c},function(c){if(console.log("order.editAddress: ",c),c.errno)util.tips(c.message);else{var f=c,g=' ';e.html(a.template(g)(f)),e.find(".js-order-address").each(function(){var a={};a.province=$(this).find(".js-province")[0],a.city=$(this).find(".js-city")[0],a.district=$(this).find(".js-district")[0];var c={};c.province=$(a.province).attr("data-value"),c.city=$(a.city).attr("data-value"),c.district=$(a.district).attr("data-value"),b.render(a,c,{withTitle:!0})}),e.find(".js-submit").click(function(){if(postdata=util.serialize(e.find("input, select, textarea")),""==postdata.realname)return util.tips("请填写收货人"),!1;if(""==postdata.mobile)return util.tips("请填写手机号"),!1;var a=/^1\d{10}$/;return a.test(postdata.mobile)?""==postdata.province?(util.tips("请选择省"),!1):""==postdata.city?(util.tips("请选择市"),!1):""==postdata.address?(util.tips("请填写详细地址"),!1):(postdata.id=f.id,void $.post("./index.php?c=order&a=order&do=edit_address",postdata,function(a){a.errno?util.tips(a.message):(e.modal("hide"),$.isFunction(d)&&d(a),util.tips("订单地址修改成功."))},"json")):(util.tips("填写手机号有误"),!1)}),e.modal("show")}},"json"),e},c.rank=function(a){$this=$(a);var b=$this.data("order-id"),c=$this.data("rank");$this.raty({cancel:!0,cancelOn:"cancel-custom-on.png",cancelOff:"cancel-custom-off.png",cancelPlace:"left",cancelHint:"重置",hints:["1","2","3","4","5"],number:6,path:"./resource/images/",starOff:"star-off-big.png",starOn:"star-on-big.png",starType:"img",size:16,score:c,targetKeep:!0,click:function(a){b&&$.post("./index.php?c=order&a=order&do=rank",{id:b,rank:a?a:0},function(a){a.errno||util.tips("修改成功!")},"json")}})},c}); \ No newline at end of file diff --git a/web/resource/js/lib/raty.min.js b/web/resource/js/lib/raty.min.js new file mode 100644 index 0000000..a5c9787 --- /dev/null +++ b/web/resource/js/lib/raty.min.js @@ -0,0 +1 @@ +!function(a){var b={init:function(c){return this.each(function(){var d=this,e=a(d).empty();d.opt=a.extend(!0,{},a.fn.raty.defaults,c),e.data("settings",d.opt),d.opt.number=b.between(d.opt.number,0,5),"/"!=d.opt.path.substring(d.opt.path.length-1,d.opt.path.length)&&(d.opt.path+="/"),"function"==typeof d.opt.score&&(d.opt.score=d.opt.score.call(d)),d.opt.score&&(d.opt.score=b.between(d.opt.score,0,d.opt.number));for(var f=1;f<=d.opt.number;f++)a("",{src:d.opt.path+(!d.opt.score||d.opt.score",{type:"hidden",name:d.opt.scoreName}).appendTo(d),d.opt.score&&d.opt.score>0&&(d.score.val(d.opt.score),b.roundStar.call(d,d.opt.score)),d.opt.iconRange&&b.fill.call(d,d.opt.score),b.setTarget.call(d,d.opt.score,d.opt.targetKeep);var g=d.opt.space?4:0,h=d.opt.width||d.opt.number*d.opt.size+d.opt.number*g;d.opt.cancel&&(d.cancel=a("",{src:d.opt.path+d.opt.cancelOff,alt:"x",title:d.opt.cancelHint,"class":"raty-cancel"}),"left"==d.opt.cancelPlace?e.prepend(" ").prepend(d.cancel):e.append(" ").append(d.cancel),h+=d.opt.size+g),d.opt.readOnly?(b.fixHint.call(d),d.cancel&&d.cancel.hide()):(e.css("cursor","pointer"),b.bindAction.call(d)),e.css("width",h)})},between:function(a,b,c){return Math.min(Math.max(parseFloat(a),b),c)},bindAction:function(){var c=this,d=a(c);d.mouseleave(function(){var a=c.score.val()||void 0;b.initialize.call(c,a),b.setTarget.call(c,a,c.opt.targetKeep),c.opt.mouseover&&c.opt.mouseover.call(c,a)});var e=c.opt.half?"mousemove":"mouseover";c.opt.cancel&&c.cancel.mouseenter(function(){a(this).attr("src",c.opt.path+c.opt.cancelOn),c.stars.attr("src",c.opt.path+c.opt.starOff),b.setTarget.call(c,null,!0),c.opt.mouseover&&c.opt.mouseover.call(c,null)}).mouseleave(function(){a(this).attr("src",c.opt.path+c.opt.cancelOff),c.opt.mouseover&&c.opt.mouseover.call(c,c.score.val()||null)}).click(function(a){c.score.removeAttr("value"),c.opt.click&&c.opt.click.call(c,null,a)}),c.stars.bind(e,function(e){var f=parseInt(this.alt,10);if(c.opt.half){var g=parseFloat((e.pageX-a(this).offset().left)/c.opt.size),h=g>.5?1:.5;f=parseFloat(this.alt)-1+h,b.fill.call(c,f),c.opt.precision&&(f=f-h+g),b.showHalf.call(c,f)}else b.fill.call(c,f);d.data("score",f),b.setTarget.call(c,f,!0),c.opt.mouseover&&c.opt.mouseover.call(c,f,e)}).click(function(a){c.score.val(c.opt.half||c.opt.precision?d.data("score"):this.alt),c.opt.click&&c.opt.click.call(c,c.score.val(),a)})},cancel:function(c){return a(this).each(function(){var d=this,e=a(d);return e.data("readonly")===!0?this:(c?b.click.call(d,null):b.score.call(d,null),void d.score.removeAttr("value"))})},click:function(c){return a(this).each(function(){return a(this).data("readonly")===!0?this:(b.initialize.call(this,c),this.opt.click?this.opt.click.call(this,c):b.error.call(this,'you must add the "click: function(score, evt) { }" callback.'),void b.setTarget.call(this,c,!0))})},error:function(b){a(this).html(b),a.error(b)},fill:function(a){for(var b,c,d,e=this,f=e.stars.length,g=0,h=1;f>=h;h++)b=e.stars.eq(h-1),e.opt.iconRange&&e.opt.iconRange.length>g?(c=e.opt.iconRange[g],d=e.opt.single?h==a?c.on||e.opt.starOn:c.off||e.opt.starOff:a>=h?c.on||e.opt.starOn:c.off||e.opt.starOff,h<=c.range&&b.attr("src",e.opt.path+d),h==c.range&&g++):(d=e.opt.single?h==a?e.opt.starOn:e.opt.starOff:a>=h?e.opt.starOn:e.opt.starOff,b.attr("src",e.opt.path+d))},fixHint:function(){var b=a(this),c=parseInt(this.score.val(),10),d=this.opt.noRatedMsg;!isNaN(c)&&c>0&&(d=c<=this.opt.hints.length&&null!==this.opt.hints[c-1]?this.opt.hints[c-1]:c),b.data("readonly",!0).css("cursor","default").attr("title",d),this.score.attr("readonly","readonly"),this.stars.attr("title",d)},getScore:function(){var b,c=[];return a(this).each(function(){b=this.score.val(),c.push(b?parseFloat(b):void 0)}),c.length>1?c:c[0]},readOnly:function(c){return this.each(function(){var d=a(this);return d.data("readonly")===c?this:(this.cancel&&(c?this.cancel.hide():this.cancel.show()),c?(d.unbind(),d.children("img").unbind(),b.fixHint.call(this)):(b.bindAction.call(this),b.unfixHint.call(this)),void d.data("readonly",c))})},reload:function(){return b.set.call(this,{})},roundStar:function(a){var b=(a-Math.floor(a)).toFixed(2);if(b>this.opt.round.down){var c=this.opt.starOn;b0&&.6>b&&this.stars.eq(Math.ceil(a)-1).attr("src",this.opt.path+this.opt.starHalf)},initialize:function(a){a=a?b.between(a,0,this.opt.number):0,b.fill.call(this,a),a>0&&(this.opt.halfShow&&b.roundStar.call(this,a),this.score.val(a))},unfixHint:function(){for(var b=0;bmodel('module'); +load()->model('system'); + +$dos = array('delete', 'edit', 'set_permission', 'save_permission', 'set_manager', 'module'); +$do = in_array($do, $dos) ? $do : 'edit'; + +$uniacid = intval($_GPC['uniacid']); +if (empty($uniacid)) { + if ($_W['isajax']) { + iajax(-1, '请选择要编辑的平台账号'); + } + itoast('请选择要编辑的平台账号', referer(), 'error'); +} +$state = permission_account_user_role($_W['uid'], $uniacid); +$role_permission = in_array($state, array(ACCOUNT_MANAGE_NAME_FOUNDER, ACCOUNT_MANAGE_NAME_OWNER, ACCOUNT_MANAGE_NAME_MANAGER, ACCOUNT_MANAGE_NAME_VICE_FOUNDER)); +if (!$role_permission) { + if ($_W['isajax']) { + iajax(-1, '无权限操作'); + } + itoast('无权限操作!', referer(), 'error'); +} +$founders = explode(',', $_W['config']['setting']['founder']); +$founder_info = pdo_getcolumn('users', array('uid' => current($founders)), 'username'); +$account = uni_fetch($uniacid); +$_W['breadcrumb'] = $account['name']; +$headimgsrc = tomedia('headimg_' . $account['acid'] . '.jpg'); +if (is_error($account)) { + itoast($account['message']); +} + +if ('edit' == $do) { + $account_belong_user = pdo_getcolumn('uni_account_users', array('uniacid' => $uniacid, 'role' => 'owner'), 'uid'); + $permissions = pdo_fetchall('SELECT id, uid, role FROM ' . tablename('uni_account_users') . " WHERE uniacid = '$uniacid' ORDER BY uid ASC, role DESC", array(), 'uid'); + if (!empty($permissions)) { + $member = pdo_fetchall('SELECT username, uid FROM ' . tablename('users') . ' WHERE uid IN (' . implode(',', array_keys($permissions)) . ')', array(), 'uid'); + if (!empty($member)) { + $operator = $manager = $owner = $vice_founder = array(); + foreach ($permissions as $key => $per_val) { + $per_val['isfounder'] = in_array($member[$key]['uid'], $founders) ? 1 : 0; + $per_val['username'] = $member[$key]['username'] ? $member[$key]['username'] : ''; + switch ($per_val['role']) { + case 'vice_founder': + $vice_founder = $per_val; + break; + case 'owner': + $owner = $per_val; + break; + case 'manager': + $manager[] = $per_val; + break; + case 'operator': + $operator[] = $per_val; + break; + default: + break; + } + } + } + } + if ($_W['isajax']) { + iajax(0, array( + 'founder_info' => $founder_info, + 'vice_founder' => empty($vice_founder) ? '' : $vice_founder, + 'owner' => empty($owner) ? '' : $owner, + 'manager' => empty($manager) ? '' : $manager, + 'operator' => empty($operator) ? '' : $operator, + 'create_user_url' => $_W['siteroot'] . 'web' . ltrim(url('user/create'), '.'), + )); + } + template('account/manage-users'); +} + +if ('delete' == $do) { + $uid = intval($_GPC['uid']); + if (empty($uid)) { + iajax(-1, '请选择要删除的用户!'); + } + $data = array( + 'uniacid' => $uniacid, + 'uid' => $uid, + ); + $exists = pdo_get('uni_account_users', array('uniacid' => $uniacid, 'uid' => $uid)); + if (empty($exists)) { + iajax(-1, '该平台账号下不存在该用户!'); + } + + if (ACCOUNT_MANAGE_NAME_MANAGER == $state && (ACCOUNT_MANAGE_NAME_OWNER == $exists['role'] || ACCOUNT_MANAGE_NAME_MANAGER == $exists['role'])) { + iajax(-1, '管理员不可操作其他管理员'); + } + $result = pdo_delete('uni_account_users', $data); + if ($result) { + if (ACCOUNT_MANAGE_NAME_OPERATOR == $exists['role']) { + pdo_delete('users_permission', $data); + } + pdo_delete('users_lastuse', $data); + pdo_delete('system_stat_visit', $data); + pdo_delete('users_operate_history', $data); + iajax(0, '删除成功!', referer()); + } else { + iajax(-1, '删除失败,请重试'); + } +} + +if ('set_manager' == $do) { + $username = safe_gpc_string($_GPC['username']); + $user = user_single(array('username' => $username)); + + if (!empty($user)) { + if (2 != $user['status']) { + iajax(3, '用户未通过审核或不存在!', ''); + } + + if (ACCOUNT_OPERATE_CLERK == $user['type']) { + iajax(-1, '该用户是应用操作员,不能成为账号的操作员!', ''); + } + + $addtype = intval($_GPC['addtype']); + if (ACCOUNT_MANAGE_TYPE_OWNER == $addtype) { + $user_end_time = user_end_time($user['uid']); + $account_end_time = 0 == $user_end_time ? 0 : strtotime($user_end_time); + pdo_update('account', array('endtime' => $account_end_time), array('uniacid' => $uniacid)); + } + + if (!in_array($addtype, array(ACCOUNT_MANAGE_TYPE_OPERATOR, ACCOUNT_MANAGE_TYPE_MANAGER, ACCOUNT_MANAGE_TYPE_OWNER, ACCOUNT_MANAGE_TYPE_VICE_FOUNDER))) { + iajax(-1, '添加使用者类型有误,只能添加操作员/管理员/主管理员/副创始人!'); + } + if (in_array($user['uid'], $founders)) { + if (ACCOUNT_MANAGE_TYPE_OWNER == $addtype) { + pdo_delete('uni_account_users', array('uniacid' => $uniacid, 'role' => ACCOUNT_MANAGE_NAME_OWNER)); + iajax(0, '修改成功!', ''); + } + iajax(1, '不可操作网站创始人!', ''); + } + if (ACCOUNT_MANAGE_TYPE_OWNER == $addtype && !in_array($_W['uid'], $founders)) { + $creat_limit = permission_user_account_num($user['uid']); + if ($creat_limit[TYPE_SIGN . '_limit'] <= 0) { + itoast(error(5, ACCOUNT_TYPE_NAME . '创建数量已达上限'), '', 'error'); + } + } + + $data = array( + 'uniacid' => $uniacid, + 'uid' => $user['uid'], + ); + + $exists = pdo_get('uni_account_users', $data); + if (empty($exists)) { + if (ACCOUNT_MANAGE_TYPE_OWNER == $addtype) { + if (ACCOUNT_MANAGE_NAME_MANAGER == $state) { + iajax(4, '管理员不可操作主管理员', ''); + } + $vice_founder = pdo_get('uni_account_users', array('uniacid' => $uniacid, 'role' => ACCOUNT_MANAGE_NAME_VICE_FOUNDER)); + if (!empty($vice_founder) && $user['owner_uid'] != $vice_founder['uid']) { + iajax(-1, '只能修改平台副创始人下的用户为主管理员!'); + } + $owner = pdo_get('uni_account_users', array('uniacid' => $uniacid, 'role' => 'owner')); + if (empty($owner)) { + $data['role'] = ACCOUNT_MANAGE_NAME_OWNER; + } else { + $result = pdo_update('uni_account_users', $data, array('id' => $owner['id'])); + if ($result) { + pdo_delete('users_permission', array('uniacid' => $uniacid, 'uid' => $user['uid'])); + cache_clean(cache_system_key('user_accounts')); + //cache_build_account_modules($uniacid, $user['uid']); + iajax(0, '修改成功!', ''); + } else { + iajax(1, '修改失败!', ''); + } + exit; + } + } elseif (ACCOUNT_MANAGE_TYPE_MANAGER == $addtype) { + if (ACCOUNT_MANAGE_NAME_MANAGER == $state) { + iajax(4, '管理员不可操作管理员', ''); + } + $data['role'] = ACCOUNT_MANAGE_NAME_MANAGER; + } elseif (ACCOUNT_MANAGE_TYPE_OPERATOR == $addtype) { + $data['role'] = ACCOUNT_MANAGE_NAME_OPERATOR; + } + pdo_delete('uni_account_users', array('uniacid' => $uniacid, 'uid' => $user['uid'])); + $result = pdo_insert('uni_account_users', $data); + + if ($result) { + if (ACCOUNT_MANAGE_TYPE_OWNER == $addtype) { + pdo_delete('users_permission', array('uniacid' => $uniacid, 'uid' => $user['uid'])); + } + if (in_array($addtype, array(ACCOUNT_MANAGE_TYPE_MANAGER, ACCOUNT_MANAGE_TYPE_OPERATOR))) { + permission_account_user_init($user['uid'], $uniacid); + } + cache_clean(cache_system_key('user_accounts')); + //cache_build_account_modules($uniacid, $user['uid']); + iajax(0, '添加成功!', ''); + } else { + iajax(1, '添加失败!', ''); + } + } else { + $permissions = table('users_permission')->getAllUserPermission($user['uid'], $uniacid); + $modulelist = uni_modules(); + if (!empty($permissions)) { + $i = 0; + foreach ($permissions as $permission) { + if ($i >= 3) { + break; + } + if (!in_array($permission['type'], array_keys($modulelist))) { + continue; + } + $module_info = module_fetch($permission['type']); + $modules_str .= $module_info['title'] . ','; + ++$i; + } + } + + if (empty($permissions) && !empty($exists)) { + if (ACCOUNT_MANAGE_NAME_OPERATOR == $exists['role']) { + $role_name = '操作员'; + } elseif (ACCOUNT_MANAGE_NAME_MANAGER == $exists['role']) { + $role_name = '管理员'; + } elseif (ACCOUNT_MANAGE_NAME_OWNER == $exists['role']) { + $role_name = '主管理员'; + } + + iajax(2, "添加平台使用者失败, " . $username . ", 已经是公众号的" . $role_name . ' ,请勿重复添加!', ''); + } else { + iajax(2, "添加平台使用者失败, " . $username . ", 已经是 " . rtrim($modules_str, ',') . '的应用操作员,请先取消其应用内操作员身份后再添加平台使用者!', ''); + } + } + } else { + iajax(-1, '用户不存在!', ''); + } +} + +if ('set_permission' == $do || 'save_permission' == $do) { + $uid = intval($_GPC['uid']); + $user = user_single(array('uid' => $uid)); + if (empty($user)) { + if ($_W['isajax']) { + iajax(-1, '您操作的用户不存在或是已经被删除'); + } + itoast('您操作的用户不存在或是已经被删除!', '', ''); + } + $role = permission_account_user_role($_W['uid'], $uniacid); + if (empty($role)) { + if ($_W['isajax']) { + iajax(-1, '此用户没有操作该统一公众号的权限,请选指派“管理员”或是“操作员”权限!'); + } + itoast('此用户没有操作该统一公众号的权限,请选指派“管理员”或是“操作员”权限!', '', ''); + } + $module_permission = permission_account_user_menu($uid, $uniacid, 'modules'); + + if ('all' == current($module_permission)) { + $module_permission_keys = array(); + $module_permission_all = 1; + } else { + $module_permission_keys = array_keys($module_permission); + $module_permission_all = 0; + } + $user_all_module_permission = table('users_permission')->getAllUserModulePermission($uid, $uniacid); + if ($account->supportVersion) { + $version_modules = array(); + $version_all = miniapp_version_all($uniacid); + if (!empty($version_all)) { + foreach ($version_all as $key => $version) { + if (!empty($version['modules'])) { + $version_modules = array_merge($version_modules, array_keys($version['modules'])); + } + } + } + foreach ($version_modules as $version_module) { + $module[$version_module] = module_fetch($version_module); + } + } else { + $module = uni_modules_by_uniacid($uniacid); + } + $user_modules_permissions = array(); + if (!empty($module)) { + foreach ($module as $module_name_key => $value) { + if (1 == $value['issystem']) { + unset($module[$module_name_key]); + continue; + } + if (!empty($user_all_module_permission[$module_name_key]['permission'])) { + $have_module_permission = explode('|', $user_all_module_permission[$module_name_key]['permission']); + } else { + $have_module_permission = array(); + } + $user_modules_permissions[$module_name_key] = array('module_title' => $value['title'], 'permission' => array()); + $permissions = module_permission_fetch($module_name_key); + if (empty($permissions)) { + $user_modules_permissions[$module_name_key]['permission'] = (in_array('all', $have_module_permission) || in_array('all', $module_permission)) ? array('all') : array(); + continue; + } + foreach ($permissions as $permission_info) { + $permission_info['checked'] = 0; + if (in_array($permission_info['permission'], $have_module_permission) || in_array('all', $have_module_permission) || in_array('all', $module_permission)) { + $permission_info['checked'] = 1; + } + $user_modules_permissions[$module_name_key]['permission'][] = $permission_info; + } + } + } + + foreach ($account_all_type_sign as $account_type_sign => $account_type_info) { + if (in_array($account['type'], $account_type_info['contain_type'])) { + $account_type = 'account' == $account_type_sign ? 'system' : $account_type_sign; + } + } + + $user_menu_permissions = permission_account_user_menu($uid, $uniacid, $account_type); + $menus = system_menu_permission_list($role); + + permission_account_user_init($user['uid'], $uniacid); + + if (in_array($account['type_sign'], array(ACCOUNT_TYPE_SIGN, WEBAPP_TYPE_SIGN))) { + $account_type_menu = ACCOUNT_TYPE_SIGN; + } elseif (in_array($account['type_sign'], array(ALIAPP_TYPE_SIGN, BAIDUAPP_TYPE_SIGN, TOUTIAOAPP_TYPE_SIGN))) { + $account_type_menu = WXAPP_TYPE_SIGN; + } else { + $account_type_menu = $account['type_sign']; + } + + if ('set_permission' == $do) { + if ($_W['isajax']) { + if (!empty($menus[$account_type_menu]) && !empty($menus[$account_type_menu]['section'])) { + foreach ($menus[$account_type_menu]['section'] as $section_key => &$section) { + if ($section_key == 'platform_module') { + unset($menus[$account_type_menu]['section']['platform_module']); + continue; + } + if (empty($section['menu'])) { + continue; + } + foreach ($section['menu'] as &$menu) { + + if (in_array($menu['permission_name'], $user_menu_permissions)) { + $menu['checked'] = 1; + } else { + $menu['checked'] = 0; + } + if (empty($menu['sub_permission'])) { + continue; + } + foreach ($menu['sub_permission'] as &$sub_permission) { + if (in_array($sub_permission['permission_name'], $user_menu_permissions)) { + $sub_permission['checked'] = 1; + } else { + $sub_permission['checked'] = 0; + } + } + unset($menu); + } + unset($sub_permission); + } + unset($section); + } + $result = array( + 'uni_modules_permission' => $user_modules_permissions, + 'menus' => $menus[$account_type_menu], + ); + iajax(0, $result); + } + template('account/set-permission'); + } +} + +if ('save_permission' == $do) { + $user_menu_permission_new = array(); + if (!empty($_GPC['menus'])) { + $all_menu_permission = permission_menu_name(); + foreach ($_GPC['menus'] as $permission_name) { + if (in_array($permission_name, $all_menu_permission)) { + $user_menu_permission_new[] = $permission_name; + } + } + $data = array( + 'type' => $account_type, + 'permission' => implode('|', $user_menu_permission_new), + ); + $result = permission_update_account_user($uid, $uniacid, $data); + if (is_error($result)) { + if ($_W['isajax']) { + iajax(-1, $result['message']); + } + itoast($result['message']); + } + } else { + $data = array( + 'type' => $account_type, + 'permission' => '|', + ); + $result = permission_update_account_user($uid, $uniacid, $data); + } + if (is_error($result)) { + if ($_W['isajax']) { + iajax(-1, $result['message']); + } + itoast($result['message']); + } + + + $permission_names = "'" . implode(array(PERMISSION_ACCOUNT, PERMISSION_WXAPP, PERMISSION_WEBAPP, PERMISSION_PHONEAPP, PERMISSION_ALIAPP, PERMISSION_BAIDUAPP, PERMISSION_TOUTIAOAPP, PERMISSION_SYSTEM), "','") . "'"; + pdo_query('DELETE FROM ' . tablename('users_permission') . ' WHERE uniacid = :uniacid AND uid = :uid AND type not in (' . $permission_names . ')', array(':uniacid' => $uniacid, ':uid' => $uid)); + + if (!empty($_GPC['module'])) { + $module_names = array(); + foreach ($_GPC['module'] as $module_val) { + $insert = array( + 'uniacid' => $uniacid, + 'uid' => $uid, + 'type' => $module_val, + ); + if (!empty($module[$module_val])) { + $module_names[] = $module_val; + } + if (1 == $_GPC[$module_val . '_select']) { + $insert['permission'] = 'all'; + pdo_insert('users_permission', $insert); + continue; + } else { + $data = array(); + foreach ($_GPC['module_' . $module_val] as $v) { + $data[] = $v; + } + if (!empty($data)) { + $insert['permission'] = implode('|', $data); + pdo_insert('users_permission', $insert); + } + } + } + $module_names = implode(',', $module_names); + pdo_query('DELETE FROM ' . tablename('users_operate_history') . ' WHERE uniacid = :uniacid AND uid = :uid AND module_name not in (:module_name)', array(':uniacid' => $uniacid, ':uid' => $uid, ':module_name' => $module_names)); + } else { + $module_all_permission_data = array( + 'uid' => $uid, + 'uniacid' => $uniacid, + 'type' => 'modules', + ); + $module_all_permission = pdo_get('users_permission', $module_all_permission_data); + if (empty($module_all_permission)) { + $module_all_permission_data['permission'] = 'none'; + pdo_insert('users_permission', $module_all_permission_data); + } + } + cache_delete(cache_system_key('permission', array('uniacid' => $uniacid, 'uid' => $uid))); + if ($_W['isajax']) { + iajax(0, '操作菜单权限成功!'); + } + itoast('操作菜单权限成功!', referer(), 'success'); +} + +if ('module' == $do) { + $uid = intval($_GPC['uid']); + $user = user_single($uid); + if (empty($user)) { + iajax(-1, '访问错误, 未找到指定操作用户.', ''); + } + $isfounder = user_is_founder($uid, true); + if ($isfounder) { + iajax(-1, '访问错误, 无法编辑站长.', ''); + } + $module_name = safe_gpc_string($_GPC['m']); + $module = pdo_fetch('SELECT * FROM ' . tablename('modules') . ' WHERE name = :m', array(':m' => $module_name)); + $purview = pdo_fetch('SELECT * FROM ' . tablename('users_permission') . ' WHERE uniacid = :aid AND uid = :uid AND type = :type', array(':aid' => $uniacid, ':uid' => $uid, ':type' => $module_name)); + $user_module_permissions = permission_account_user_menu($uid, $uniacid, 'modules'); + if (!empty($purview['permission'])) { + $purview['permission'] = explode('|', $purview['permission']); + } else { + $purview['permission'] = array(); + } + + $mineurl = array(); + $all = 0; + if (!empty($mods)) { + foreach ($mods as $mod) { + if ('all' == $mod['url']) { + $all = 1; + break; + } else { + $mineurl[] = $mod['url']; + } + } + } + $data = array(); + if ($module['settings']) { + $data[] = array('title' => '参数设置', 'permission' => $module_name . '_settings'); + } + if ($module['isrulefields']) { + $data[] = array('title' => '回复规则列表', 'permission' => $module_name . '_rule'); + } + $entries = module_entries($module_name); + if (!empty($entries['home'])) { + $data[] = array('title' => '微站首页导航', 'permission' => $module_name . '_home'); + } + if (!empty($entries['profile'])) { + $data[] = array('title' => '个人中心导航', 'permission' => $module_name . '_profile'); + } + if (!empty($entries['shortcut'])) { + $data[] = array('title' => '快捷菜单', 'permission' => $module_name . '_shortcut'); + } + if (!empty($entries['cover'])) { + foreach ($entries['cover'] as $cover) { + $data[] = array('title' => $cover['title'], 'permission' => $module_name . '_cover_' . $cover['do']); + } + } + if (!empty($entries['menu'])) { + foreach ($entries['menu'] as $menu) { + if (!empty($menu['multilevel'])) { + continue; + } + $data[] = array('title' => $menu['title'], 'permission' => $module_name . '_menu_' . $menu['do']); + } + } + unset($entries); + if (!empty($module['permissions'])) { + $module['permissions'] = (array)iunserializer($module['permissions']); + $data = array_merge($data, $module['permissions']); + } + foreach ($data as &$data_val) { + $data_val['checked'] = 0; + if (in_array($data_val['permission'], $purview['permission']) || in_array('all', $purview['permission']) || in_array('all', $user_module_permissions)) { + $data_val['checked'] = 1; + } + } + unset($data_val); + if (empty($data)) { + iajax(-1, '无子权限!', ''); + } else { + iajax(0, $data, ''); + } +} diff --git a/web/source/account/post.ctrl.php b/web/source/account/post.ctrl.php new file mode 100644 index 0000000..880ef33 --- /dev/null +++ b/web/source/account/post.ctrl.php @@ -0,0 +1,253 @@ +model('module'); +load()->model('cloud'); +load()->model('cache'); +load()->classs('weixin.platform'); +load()->model('utility'); +load()->func('file'); +$uniacid = intval($_GPC['uniacid']); +if (empty($uniacid)) { + $url = url('account/manage', array('account_type' => ACCOUNT_TYPE)); + if ($_W['isajax']) { + iajax(-1, '请选择要编辑的' . ACCOUNT_TYPE_NAME); + } + itoast('请选择要编辑的' . ACCOUNT_TYPE_NAME, $url, 'error'); +} +$account = uni_fetch($uniacid); +if (!$account) { + if ($_W['isajax']) { + iajax(-1, '无效的uniacid'); + } + itoast('无效的uniacid'); +} +$acid = $account['acid']; +$state = permission_account_user_role($_W['uid'], $uniacid); +$dos = array('base', 'sms', 'modules_tpl', 'edit_modules_tpl', 'operators'); +$role_permission = in_array($state, array(ACCOUNT_MANAGE_NAME_FOUNDER, ACCOUNT_MANAGE_NAME_OWNER, ACCOUNT_MANAGE_NAME_VICE_FOUNDER)); +if ($role_permission || $_W['isajax']) { + $do = in_array($do, $dos) ? $do : 'base'; +} elseif (ACCOUNT_MANAGE_NAME_MANAGER == $state) { + if (ACCOUNT_TYPE == ACCOUNT_TYPE_APP_NORMAL || ACCOUNT_TYPE == ACCOUNT_TYPE_APP_AUTH) { + header('Location: ' . url('wxapp/manage/display', array('uniacid' => $uniacid))); + exit; + } else { + $do = in_array($do, $dos) ? $do : 'modules_tpl'; + } +} else { + itoast('您是该公众号的操作员,无权限操作!', url('account/manage'), 'error'); +} + +$_W['breadcrumb'] = $account['name']; +if ('base' == $do) { + if (!$role_permission && !$_W['isajax']) { + itoast('无权限操作!', url('account/post/modules_tpl', array('uniacid' => $uniacid)), 'error'); + } + if ($_W['ispost'] && $_W['isajax']) { + if (!empty($_GPC['type'])) { + $type = safe_gpc_string($_GPC['type']); + } else { + iajax(-1, '参数错误!', ''); + } + $request_data = safe_gpc_string(trim($_GPC['request_data'])); + switch ($type) { + case 'qrcodeimgsrc': + case 'headimgsrc': + $imgsrc = safe_gpc_path($request_data); + $image_type = array( + 'qrcodeimgsrc' => 'qrcode', + 'headimgsrc' => 'logo', + ); + if (file_is_image($imgsrc)) { + $result = table('uni_account')->where('uniacid', $uniacid)->fill($image_type[$type], $imgsrc)->save(); + } else { + $result = ''; + } + break; + case 'name': + $uni_account = pdo_update('uni_account', array('name' => $request_data), array('uniacid' => $uniacid)); + $account_wechats = pdo_update($account->tablename, array('name' => $request_data), array('uniacid' => $uniacid)); + $result = ($uni_account && $account_wechats) ? true : false; + break; + case 'account': + $data = array('account' => $request_data); break; + case 'original': + $data = array('original' => $request_data); break; + case 'level': + $data = array('level' => intval($_GPC['request_data'])); break; + case 'appid': + if (!empty($request_data)) { + $hasAppid = uni_get_account_by_appid($request_data, $account['type'], $account['uniacid']); + if (!empty($hasAppid)) { + iajax(1, "{$hasAppid['key_title']}已被{$hasAppid['type_title']}[ {$hasAppid['name']} ]使用"); + } + } + $data = array('appid' => $request_data); break; + case 'key': + if (!empty($request_data) && !in_array($account['type_sign'], array(BAIDUAPP_TYPE_SIGN, TOUTIAOAPP_TYPE_SIGN))) { + $hasAppid = uni_get_account_by_appid($request_data, $account['type'], $account['uniacid']); + if (!empty($hasAppid)) { + iajax(1, "{$hasAppid['key_title']}已被{$hasAppid['type_title']}[ {$hasAppid['name']} ]使用"); + } + } + if ($account['key'] == $request_data) { + iajax(0, '修改成功!', referer()); + } + $data = array('key' => $request_data); break; + case 'secret': + if ($account['secret'] == $request_data) { + iajax(0, '修改成功!', referer()); + } + $data = array('secret' => $request_data); break; + case 'token': + $oauth = (array) uni_setting_load(array('oauth'), $uniacid); + if ($oauth['oauth'] == $acid && 4 != $account['level']) { + $acid = pdo_fetchcolumn('SELECT acid FROM ' . tablename('account_wechats') . " WHERE uniacid = :uniacid AND level = 4 AND secret != '' AND `key` != ''", array(':uniacid' => $uniacid)); + pdo_update('uni_settings', array('oauth' => iserializer(array('account' => $acid, 'host' => $oauth['oauth']['host']))), array('uniacid' => $uniacid)); + } + $data = array('token' => $request_data); + break; + case 'encodingaeskey': + $oauth = (array) uni_setting_load(array('oauth'), $uniacid); + if ($oauth['oauth'] == $acid && 4 != $account['level']) { + $acid = pdo_fetchcolumn('SELECT acid FROM ' . tablename('account_wechats') . " WHERE uniacid = :uniacid AND level = 4 AND secret != '' AND `key` != ''", array(':uniacid' => $uniacid)); + pdo_update('uni_settings', array('oauth' => iserializer(array('account' => $acid, 'host' => $oauth['oauth']['host']))), array('uniacid' => $uniacid)); + } + $data = array('encodingaeskey' => $request_data); + break; + case 'jointype': + if (in_array($account['type'], array(ACCOUNT_TYPE_OFFCIAL_NORMAL, ACCOUNT_TYPE_APP_NORMAL))) { + $result = true; + } else { + $change_type = array( + 'type' => 'account' == $account->typeSign ? ACCOUNT_TYPE_OFFCIAL_NORMAL : ACCOUNT_TYPE_APP_NORMAL, + ); + $update_type = pdo_update('account', $change_type, array('uniacid' => $uniacid)); + $result = $update_type ? true : false; + } + break; + case 'highest_visit': + if (user_is_vice_founder() || empty($_W['isfounder'])) { + iajax(1, '只有创始人可以修改!'); + } + $statistics_setting = (array) uni_setting_load(array('statistics'), $uniacid); + if (!empty($statistics_setting['statistics'])) { + $highest_visit = $statistics_setting['statistics']; + $highest_visit['founder'] = intval($_GPC['request_data']); + } else { + $highest_visit = array('founder' => intval($_GPC['request_data'])); + } + $result = pdo_update('uni_settings', array('statistics' => iserializer($highest_visit)), array('uniacid' => $uniacid)); + break; + case 'endtime': + $endtime = strtotime($_GPC['endtime']); + if ($endtime <= 0) { + iajax(1, '参数错误!'); + } + + if ($_W['isfounder']) { + $endtime = 1 != $_GPC['endtype'] ? $endtime : 0; + + } else { + $owner_id = pdo_getcolumn('uni_account_users', array('uniacid' => $uniacid, 'role' => 'owner'), 'uid'); + $user_endtime = pdo_getcolumn('users', array('uid' => $owner_id), 'endtime'); + + if ($user_endtime != USER_ENDTIME_GROUP_UNLIMIT_TYPE && $user_endtime != USER_ENDTIME_GROUP_EMPTY_TYPE && $user_endtime < $endtime && !empty($user_endtime)) { + iajax(1, '设置到期日期不能超过' . user_end_time($owner_id)); + } + } + $result = pdo_update('account', array('endtime' => $endtime), array('uniacid' => $uniacid)); + break; + case 'attachment_limit': + if (user_is_vice_founder() || empty($_W['isfounder'])) { + iajax(1, '只有创始人可以修改!'); + } + $has_uniacid = pdo_getcolumn('uni_settings', array('uniacid' => $uniacid), 'uniacid'); + if ($_GPC['request_data'] < 0) { + $attachment_limit = -1; + } else { + $attachment_limit = intval($_GPC['request_data']); + } + if (empty($has_uniacid)) { + $result = pdo_insert('uni_settings', array('attachment_limit' => $attachment_limit, 'uniacid' => $uniacid)); + } else { + $result = pdo_update('uni_settings', array('attachment_limit' => $attachment_limit), array('uniacid' => $uniacid)); + } + break; + } + if (!in_array($type, array('qrcodeimgsrc', 'headimgsrc', 'name', 'endtime', 'jointype', 'highest_visit', 'attachment_limit'))) { + $result = pdo_update($account->tablename, $data, array('uniacid' => $uniacid)); + } + if ($result) { + cache_delete(cache_system_key('uniaccount', array('uniacid' => $uniacid))); + cache_delete(cache_system_key('accesstoken', array('uniacid' => $uniacid))); + cache_delete(cache_system_key('statistics', array('uniacid' => $uniacid))); + iajax(0, '修改成功!', referer()); + } else { + iajax(1, '修改失败!', ''); + } + } + + if(!$_W['isadmin']){ + $owner_id = pdo_getcolumn('uni_account_users', array('uniacid' => $uniacid, 'role' => 'owner'), 'uid'); + $user_endtime = user_end_time($owner_id); + } + if ($_W['setting']['platform']['authstate']) { + $account_platform = new WeixinPlatform(); + $preauthcode = $account_platform->getPreauthCode(); + if (is_error($preauthcode)) { + if (40013 == $preauthcode['errno']) { + $url = '微信开放平台 appid 链接不成功,请检查修改后再试' . "去设置"; + } else { + $url = "{$preauthcode['message']}"; + } + + $authurl = array( + 'errno' => 1, + 'url' => $url, + ); + } else { + $authurl_type = $account['type'] == 4 ? ACCOUNT_PLATFORM_API_LOGIN_WXAPP : ACCOUNT_PLATFORM_API_LOGIN_ACCOUNT; + $callurl = $authurl_type == ACCOUNT_PLATFORM_API_LOGIN_WXAPP ? 'index.php?c=wxapp&a=auth&do=forward' : 'index.php?c=account&a=auth&do=forward'; + $authurl = array( + 'errno' => 0, + 'url' => sprintf(ACCOUNT_PLATFORM_API_LOGIN, $account_platform->appid, $preauthcode, urlencode($GLOBALS['_W']['siteroot'] . $callurl), $authurl_type), + ); + } + } + $account['start'] = date('Y-m-d', $account['starttime']); + $account['end'] = in_array($account['endtime'], array(USER_ENDTIME_GROUP_EMPTY_TYPE, USER_ENDTIME_GROUP_UNLIMIT_TYPE)) ? '永久' : date('Y-m-d', $account['endtime']); + $account['endtype'] = (in_array($account['endtime'], array(USER_ENDTIME_GROUP_EMPTY_TYPE, USER_ENDTIME_GROUP_UNLIMIT_TYPE)) || $account['endtime'] == 0) ? 1 : 2; + $uni_setting = (array) uni_setting_load(array('statistics', 'attachment_limit', 'attachment_size'), $uniacid); + $account['highest_visit'] = empty($uni_setting['statistics']['founder']) ? 0 : $uni_setting['statistics']['founder']; + + $attachment_limit = intval($uni_setting['attachment_limit']); + if (0 == $attachment_limit) { + $upload = setting_load('upload'); + $attachment_limit = empty($upload['upload']['attachment_limit']) ? 0 : intval($upload['upload']['attachment_limit']); + } + if ($attachment_limit <= 0) { + $attachment_limit = -1; + } + $account['attachment_limit'] = intval($attachment_limit); + $account['switchurl_full'] = $_W['siteroot'] . 'web/' . ltrim($account['switchurl'], './'); + $account['endtime'] = strlen($account['endtime']) == 10 ? $account['endtime'] : time(); + $account['headimgsrc'] = $account['logo']; + $account['qrcodeimgsrc'] = $account['qrcode']; + $account['switchurl_full'] = $_W['siteroot'] . 'web/' . ltrim($account['switchurl'], './'); + $account['siteurl'] = $account['type_sign'] != WXAPP_TYPE_SIGN ? $_W['siteroot'] : str_replace('http://', 'https://', $_W['siteroot']); + $account['service_url'] = $account['siteurl'] . 'api.php?id=' . $account['acid']; + $account['type_class'] = $account_all_type_sign[$account['type_sign']]['icon']; + $account['owner_endtime'] = $user_endtime; + $account['support_version'] = $account->supportVersion; + $uniaccount = array(); + $uniaccount = pdo_get('uni_account', array('uniacid' => $uniacid)); + + if ($_W['isajax']) { + iajax(0, $account); + } else { + template('account/manage-base'); + } +} diff --git a/web/source/system/optimize.ctrl.php b/web/source/system/optimize.ctrl.php new file mode 100644 index 0000000..9bdfadb --- /dev/null +++ b/web/source/system/optimize.ctrl.php @@ -0,0 +1,79 @@ +func('cache'); + +$dos = array('opcache'); +$do = in_array($do, $dos) ? $do : 'index'; + +if ('opcache' == $do) { + opcache_reset(); + if ($_W['isw7_request']) { + iajax(0, '清空缓存成功'); + } + itoast('清空缓存成功', url('system/optimize'), 'success'); +} else { + $cache_type = cache_type(); + $clear = array('url' => url('system/updatecache', array('do' => 'updatecache')), 'title' => '更新缓存'); + $extensions = array( + 'memcache' => array( + 'support' => extension_loaded('memcache'), + 'status' => 'memcache' == $cache_type, + 'clear' => $clear, + ), + 'redis' => array( + 'support' => extension_loaded('redis'), + 'status' => 'redis' == $cache_type, + 'clear' => $clear, + ), + 'opcache' => array( + 'support' => function_exists('opcache_get_configuration'), + 'status' => ini_get('opcache.enable') || ini_get('opcache.enable_cli'), + 'clear' => array( + 'url' => url('system/optimize/opcache'), + 'title' => '清空缓存', + ), + ), + ); + $slave = $_W['config']['db']; + $setting = $_W['config']['setting']; + + if ($extensions['memcache']['status']) { + $memobj = cache_memcache(); + if (!empty($memobj) && method_exists($memobj, 'getExtendedStats')) { + $status = $memobj->getExtendedStats(); + if (!empty($status)) { + foreach ($status as $server => $row) { + $data_status[] = '已用:' . round($row['bytes'] / 1048576, 2) . ' M / 共:' . round($row['limit_maxbytes'] / 1048576) . ' M'; + } + $extensions['memcache']['extra'] = ', ' . implode(', ', $data_status); + } + } + } + if ($extensions['redis']['status']) { + $redisobj = cache_redis(); + if (!empty($redisobj) && method_exists($redisobj, 'info')) { + $status = $redisobj->info(); + if (!empty($status)) { + $extensions['redis']['extra'] = '消耗峰值:' . round($status['used_memory_peak'] / 1048576, 2) . ' M/ 内存总量:' . round($status['used_memory'] / 1048576, 2) . ' M'; + } + } + } + if ($_W['isw7_request']) { + $message = array( + 'extensions' => $extensions, + 'slave_status' => $slave['slave_status'], + 'extensions' => $extensions, + 'session_setting' => array( + 'memcache' => $setting['memcache']['session'], + 'redis' => $setting['redis']['session'] + ), + 'slave_except_table' => !empty($slave['common']['slave_except_table']) ? $slave['common']['slave_except_table']: array(), + 'proxy_host' => !empty($setting['proxy']['host']) ? $setting['proxy']['host'] : '' + ); + iajax(0, $message); + } + template('system/optimize'); +} \ No newline at end of file diff --git a/web/source/user/profile.ctrl.php b/web/source/user/profile.ctrl.php new file mode 100644 index 0000000..38aede2 --- /dev/null +++ b/web/source/user/profile.ctrl.php @@ -0,0 +1,450 @@ +model('user'); +load()->func('file'); +load()->classs('oauth2/oauth2client'); +load()->model('setting'); + +$dos = array('base', 'post', 'bind', 'validate_mobile', 'bind_mobile', 'unbind', 'check_mobile_sms_code', 'change_mobile'); +$do = in_array($do, $dos) ? $do : 'base'; + +if ('post' == $do) { + $type = trim($_GPC['type']); + $extra_filed_key = safe_gpc_string($_GPC['extra_field_key']); + $extra_filed_val = safe_gpc_string($_GPC['extra_field_val']); + if ($_W['isfounder']) { + $uid = is_array($_GPC['uid']) ? 0 : intval($_GPC['uid']); + } else { + $uid = $_W['uid']; + } + if (empty($uid) || empty($type)) { + iajax(-1, '参数错误,请刷新后重试!', ''); + } + $user = user_single($uid); + if (empty($user)) { + iajax(-1, '用户不存在或已经被删除!', ''); + } + + if (USER_STATUS_CHECK == $user['status'] || USER_STATUS_BAN == $user['status']) { + iajax(-1, '访问错误,该用户未审核或者已被禁用,请先修改用户状态!', ''); + } + + $users_profile_exist = table('users_profile')->getByUid($uid); + if ('birth' == $type) { + if ($users_profile_exist['year'] == $_GPC['year'] && $users_profile_exist['month'] == $_GPC['month'] && $users_profile_exist['day'] == $_GPC['day']) { + iajax(0, '未作修改!', ''); + } + } elseif ('reside' == $type) { + if ($users_profile_exist['province'] == $_GPC['province'] && $users_profile_exist['city'] == $_GPC['city'] && $users_profile_exist['district'] == $_GPC['district']) { + iajax(0, '未作修改!', ''); + } + } else { + if (in_array($type, array('username', 'password', 'welcome_link'))) { + if ($user[$type] == $_GPC[$type] && 'password' != $type) { + iajax(0, '未做修改!', ''); + } + } else { + if ($users_profile_exist[$type] == $_GPC[$type] && empty($extra_filed_key)) { + iajax(0, '未作修改!', ''); + } + } + } + switch ($type) { + case 'avatar': + case 'realname': + case 'address': + case 'qq': + case 'mobile': + if ('mobile' == $type) { + $match = preg_match(REGULAR_MOBILE, trim($_GPC[$type])); + if (empty($match)) { + iajax(-1, '手机号不正确', ''); + } + $users_mobile = pdo_get('users_profile', array('mobile' => trim($_GPC[$type]), 'uid <>' => $uid)); + $bind_mobile = pdo_get('users_bind', array('bind_sign' => trim($_GPC[$type]), 'uid <>' => $uid)); + if (!empty($users_mobile) || !empty($bind_mobile)) { + iajax(-1, '手机号已存在,请联系管理员', ''); + } + } + if ($users_profile_exist) { + $result = pdo_update('users_profile', array($type => trim($_GPC[$type])), array('uid' => $uid)); + } else { + $data = array( + 'uid' => $uid, + 'createtime' => TIMESTAMP, + $type => safe_gpc_string($_GPC[$type]), + ); + $result = pdo_insert('users_profile', $data); + } + if ('mobile' == $type) { + $data = array( + 'uid' => $uid, + 'bind_sign' => trim($_GPC[$type]), + 'third_nickname' => trim($_GPC[$type]), + 'third_type' => USER_REGISTER_TYPE_MOBILE, + ); + $users_bind_exist = pdo_get('users_bind', array('uid' => $uid, 'third_type' => USER_REGISTER_TYPE_MOBILE)); + if ($users_bind_exist) { + $result_bind = pdo_update('users_bind', $data, array('uid' => $uid, 'third_type' => USER_REGISTER_TYPE_MOBILE)); + } else { + $result_bind = pdo_insert('users_bind', $data); + } + if (!$result_bind) { + iajax(-1, '操作失败,请联系管理员解决!', ''); + } + } + break; + case 'username': + if (!$_W['isadmin'] && $_W['uid'] != $user['owner_uid']) { + iajax(-1, '无权限修改,请联系网站创始人!'); + } + $username = safe_gpc_string($_GPC['username']); + $name_exist = pdo_get('users', array('username' => $username)); + if (!empty($name_exist)) { + iajax(-1, '用户名已存在,请更换其他用户名!', ''); + } + $result = pdo_update('users', array('username' => $username), array('uid' => $uid)); + break; + case 'vice_founder_name': + $userinfo = user_single(array('username' => safe_gpc_string($_GPC['vice_founder_name']))); + + if (empty($userinfo) || ACCOUNT_MANAGE_GROUP_VICE_FOUNDER != $userinfo['founder_groupid']) { + iajax(-1, '用户不存在或该用户不是副创始人', ''); + } + pdo_update('users', array('owner_uid' => $userinfo['uid']), array('uid' => $uid)); + $founder_own_user_table = table('users_founder_own_users'); + $founder_own_user_exists = $founder_own_user_table->getFounderByUid($uid); + + if (!empty($founder_own_user_exists)) { + $result = $founder_own_user_table->updateOwnUser($uid, $userinfo['uid']); + } else { + $result = $founder_own_user_table->addOwnUser($uid, $userinfo['uid']); + } + + + if ($result) { + $uni_account_users = table('uni_account_users'); + $synchronize_data = $uni_account_users->where(array('uid' => $uid, 'role' => 'owner'))->getall('uniacid'); + if (!empty($synchronize_data)) { + foreach ($synchronize_data as $k => $v) { + $founder_id = ''; + $founder_id = table('uni_account_users')->where(array('uniacid' => $k, 'role' => 'vice_founder'))->getcolumn('id'); + + if ($founder_id) { + $uni_account_result = table('uni_account_users')->where(array('id' => $founder_id))->fill(array('uid' => $userinfo['uid']))->save(); + } else { + $save_data = array( + 'uniacid' => $k, + 'uid' => $userinfo['uid'], + 'role' => 'vice_founder', + 'rank' => 0, + 'createtime' => 0 + ); + $uni_account_result = table('uni_account_users')->fill($save_data)->save(); + } + } + } + } + + break; + case 'remark': + $result = pdo_update('users', array('remark' => safe_gpc_string($_GPC['remark'])), array('uid' => $uid)); + break; + case 'welcome_link': + $welcome_link = intval($_GPC['welcome_link']); + $result = pdo_update('users', array('welcome_link' => $welcome_link), array('uid' => $uid)); + break; + case 'password': + if ($_GPC['newpwd'] !== $_GPC['renewpwd']) { + iajax(-1, '两次密码不一致!', ''); + } + $_GPC['newpwd'] = safe_gpc_string($_GPC['newpwd']); + $check_safe = safe_check_password($_GPC['newpwd']); + if (is_error($check_safe)) { + iajax(-1, $check_safe['message']); + } + + if (!$_W['isfounder'] && empty($user['register_type'])) { + $pwd = user_password($_GPC['oldpwd'], $uid); + $pwd_hash = user_password_hash($pwd, $uid); + if ($pwd_hash != $user['hash']) { + iajax(-1, '原密码不正确!', ''); + } + } + $newpwd = user_password($_GPC['newpwd'], $uid); + $newpwd_hash = user_password_hash($newpwd, $uid); + if ($newpwd_hash == $user['hash']) { + iajax(0, '未作修改!', ''); + } + $result = pdo_update('users', array('password' => $newpwd), array('uid' => $uid)); + break; + case 'endtime': + if (!$_W['isfounder']) { + iajax(-1, '无权限操作!'); + } + if (1 == $_GPC['endtype']) { + $endtime = 0; + } else { + $endtime = strtotime($_GPC['endtime']); + } + if (user_is_vice_founder() && !empty($_W['user']['endtime']) && ($endtime > $_W['user']['endtime'] || empty($endtime))) { + iajax(-1, '副创始人给用户设置的时间不能超过自己的到期时间'); + } + $result = pdo_update('users', array('endtime' => $endtime), array('uid' => $uid)); + pdo_update('users_profile', array('send_expire_status' => 0), array('uid' => $uid)); + $uni_account_user = pdo_getall('uni_account_users', array('uid' => $uid, 'role' => 'owner')); + if (!empty($uni_account_user)) { + foreach ($uni_account_user as $account) { + cache_delete(cache_system_key('uniaccount', array('uniacid' => $account['uniacid']))); + } + } + break; + case 'birth': + if ($users_profile_exist) { + $result = pdo_update('users_profile', array('birthyear' => intval($_GPC['year']), 'birthmonth' => intval($_GPC['month']), 'birthday' => intval($_GPC['day'])), array('uid' => $uid)); + } else { + $data = array( + 'uid' => $uid, + 'createtime' => TIMESTAMP, + 'birthyear' => intval($_GPC['year']), + 'birthmonth' => intval($_GPC['month']), + 'birthday' => intval($_GPC['day']), + ); + $result = pdo_insert('users_profile', $data); + } + break; + case 'reside': + $province = safe_gpc_string($_GPC['province']); + $city = safe_gpc_string($_GPC['city']); + $district = safe_gpc_string($_GPC['district']); + if ($users_profile_exist) { + $result = pdo_update('users_profile', array('resideprovince' => $province, 'residecity' => $city, 'residedist' => $district), array('uid' => $uid)); + } else { + $data = array( + 'uid' => $uid, + 'createtime' => TIMESTAMP, + 'resideprovince' => $province, + 'residecity' => $city, + 'residedist' => $district, + ); + $result = pdo_insert('users_profile', $data); + } + break; + default: + $allow_fields = array( + 'realname', 'nickname', 'avatar', 'qq', 'mobile', 'gender', 'birthyear', 'birthmonth', 'birthday', 'constellation', 'zodiac', 'idcard', 'studentid', 'grade', 'address', 'zipcode', 'nationality', 'resideprovince', 'residecity', 'residedist', 'graduateschool', 'company', 'education', 'occupation', 'position', 'revenue', 'affectivestatus', 'lookingfor', 'bloodtype', 'height', 'weight', 'alipay', 'msn', 'email', 'taobao', 'site', 'bio', 'interest', + ); + if (empty($extra_filed_key) || !in_array($extra_filed_key, $allow_fields)) { + iajax(-1, '参数错误', ''); + } + if ($users_profile_exist) { + $result = pdo_update('users_profile', array($extra_filed_key => $extra_filed_val), array('uid' => $uid)); + } else { + $data = array( + 'uid' => $uid, + $extra_filed_key => $extra_filed_val, + ); + $result = pdo_insert('users_profile', $data); + } + break; + } + if ($result) { + pdo_update('users_profile', array('edittime' => TIMESTAMP), array('uid' => $uid)); + $type == 'password' ? iajax(0, '修改成功,请重新登录!', url('user/login')) : iajax(0, '修改成功!', ''); + } else { + iajax(-1, '修改失败,请稍候重试!', ''); + } +} + +if ('base' == $do) { + $user_type = !empty($_GPC['user_type']) ? trim($_GPC['user_type']) : PERSONAL_BASE_TYPE; + $user = $_W['user']; + $user['last_visit'] = date('Y-m-d H:i:s', $user['lastvisit']); + $user['joindate'] = date('Y-m-d H:i:s', $user['joindate']); + $user['url'] = user_invite_register_url($_W['uid']); + + $profile = pdo_get('users_profile', array('uid' => $_W['uid'])); + $profile = user_detail_formate($profile); + + $redirect_urls = array( + array('id' => WELCOME_DISPLAY_TYPE, 'name' => '用户欢迎页'), + array('id' => PLATFORM_DISPLAY_TYPE, 'name' => '最后进入的平台或应用'), + ); + $support_login_urls = user_support_urls(); + + $lists = table('users_bind')->getAllByUid($_W['uid']); + $bind_qq = array(); + $bind_wechat = array(); + $bind_mobile = array(); + if (!empty($lists)) { + foreach ($lists as $list) { + switch ($list['third_type']) { + case USER_REGISTER_TYPE_QQ: + $bind_qq = $list; + break; + case USER_REGISTER_TYPE_WECHAT: + $bind_wechat = $list; + break; + case USER_REGISTER_TYPE_MOBILE: + $bind_mobile = $list; + break; + } + } + } + + $endtime = $user['endtime']; + if (USER_ENDTIME_GROUP_EMPTY_TYPE == $endtime || USER_ENDTIME_GROUP_UNLIMIT_TYPE == $endtime) { + $endtime = '永久'; + } else { + $endtime = date('Y-m-d', $endtime); + } + + $setting_sms_sign = setting_load('site_sms_sign'); + $bind_sign = !empty($setting_sms_sign['site_sms_sign']['register']) ? $setting_sms_sign['site_sms_sign']['register'] : ''; + + template('user/profile'); +} + +if ('bind' == $do) { + $setting_sms_sign = setting_load('site_sms_sign'); + $bind_sign = !empty($setting_sms_sign['site_sms_sign']['register']) ? $setting_sms_sign['site_sms_sign']['register'] : ''; + + $user = table('users')->getById($_W['uid']); + $user_profile = table('users_profile')->getByUid($_W['uid']); + + $bind_info = table('users_bind')->getAllByUid($_W['uid']); + + $signs = array_keys($bind_info); + + if (!empty($user['openid']) && !in_array($user['openid'], $signs)) { + pdo_insert('users_bind', array('uid' => $user['uid'], 'bind_sign' => $user['openid'], 'third_type' => $user['register_type'], 'third_nickname' => $user_profile['nickname'])); + } + + if (!empty($user_profile['mobile']) && !in_array($user_profile['mobile'], $signs)) { + pdo_insert('users_bind', array('uid' => $user_profile['uid'], 'bind_sign' => $user_profile['mobile'], 'third_type' => USER_REGISTER_TYPE_MOBILE, 'third_nickname' => $user_profile['mobile'])); + } + + $lists = table('users_bind')->getAllByUid($_W['uid']); + + $bind_qq = array(); + $bind_wechat = array(); + $bind_mobile = array(); + + if (!empty($lists)) { + foreach ($lists as $list) { + switch ($list['third_type']) { + case USER_REGISTER_TYPE_QQ: + $bind_qq = $list; + break; + case USER_REGISTER_TYPE_WECHAT: + $bind_wechat = $list; + break; + case USER_REGISTER_TYPE_MOBILE: + $bind_mobile = $list; + break; + } + } + } + + $support_login_urls = user_support_urls(); + + template('user/bind'); +} + +if (in_array($do, array('validate_mobile', 'bind_mobile')) || USER_REGISTER_TYPE_MOBILE == $_GPC['bind_type'] && 'unbind' == $do) { + $user_bind = table('users_bind')->getByTypeAndUid(USER_REGISTER_TYPE_MOBILE, $_W['uid']); + + $mobile = safe_gpc_string($_GPC['mobile']); + $type = trim($_GPC['type']); + + $mobile_exists = table('users_profile')->where('uid !=', $_W['uid'])->getByMobile($mobile); + if (empty($mobile)) { + iajax(-1, '手机号不能为空'); + } + if (!preg_match(REGULAR_MOBILE, $mobile)) { + iajax(-1, '手机号格式不正确'); + } + + if (!empty($type) && $mobile != $user_bind['bind_sign']) { + iajax(-1, '请输入已绑定的手机号'); + } + + if (empty($type) && !empty($mobile_exists)) { + iajax(-1, '手机号已存在'); + } +} +if ('validate_mobile' == $do) { + $user = array('username' => safe_gpc_string($_GPC['mobile'])); + $mobile_exists = user_check($user); + if ($mobile_exists) { + iajax(-1, '手机号已经存在'); + } + iajax(0, '本地校验成功'); +} + +if ('bind_mobile' == $do) { + if ($_W['isajax'] && $_W['ispost']) { + $bind_info = OAuth2Client::create('mobile')->bind(); + + $user = array('username' => safe_gpc_string($_GPC['mobile'])); + $mobile_exists = user_check($user); + if ($mobile_exists) { + iajax(-1, '手机号已经存在'); + } + + if (is_error($bind_info)) { + iajax(-1, $bind_info['message']); + } + iajax(0, '绑定成功', url('user/profile/bind')); + } else { + iajax(-1, '非法请求'); + } +} + +if ('change_mobile' == $do) { + $step = 1; + $bind_mobile = table('users_bind')->getByTypeAndUid(USER_REGISTER_TYPE_MOBILE, $_W['uid']); + $setting_sms_sign = setting_load('site_sms_sign'); + $bind_sign = !empty($setting_sms_sign['site_sms_sign']['register']) ? $setting_sms_sign['site_sms_sign']['register'] : ''; + template('user/change-mobile'); +} + +if ('check_mobile_sms_code' == $do) { + if ($_W['isajax'] && $_W['ispost']) { + $check_result = OAuth2Client::create('mobile')->paramValidate(); + if (is_error($check_result)) { + iajax(-1, $check_result['message']); + } + $check_authcode = authcode(safe_gpc_string($_GPC['mobile']), 'ENCODE'); + $message = array( + 'message' => '验证成功', + 'check_authcode' => $check_authcode + ); + iajax(0, $message); + } else { + iajax(-1, '非法请求'); + } +} + +if ('unbind' == $do) { + $types = array(1 => 'qq', 2 => 'wechat', 3 => 'mobile'); + if (!in_array($_GPC['bind_type'], array(USER_REGISTER_TYPE_QQ, USER_REGISTER_TYPE_WECHAT, USER_REGISTER_TYPE_MOBILE))) { + iajax(-1, '类型错误'); + } + $bind_type = $types[$_GPC['bind_type']]; + if ($_W['isajax'] && $_W['ispost']) { + $unbind_info = OAuth2Client::create($bind_type, $_W['setting']['thirdlogin'][$bind_type]['appid'], $_W['setting']['thirdlogin'][$bind_type]['appsecret'])->unbind(); + + if (is_error($unbind_info)) { + iajax(-1, $unbind_info['message']); + } + $settings = $_W['setting']['copyright']; + if ($_W['isadmin'] && $settings['login_verify_status']) { + $settings['login_verify_status'] = 0; + setting_save($settings, 'copyright'); + } + iajax(0, '解绑成功', url('user/profile/bind')); + } + iajax(-1, '非法请求'); +} \ No newline at end of file diff --git a/web/themes/default/system/optimize.html b/web/themes/default/system/optimize.html new file mode 100644 index 0000000..45845cb --- /dev/null +++ b/web/themes/default/system/optimize.html @@ -0,0 +1,49 @@ +{template 'common/header'} +
+
    +
    +
    + + + + + + + + + + + + {loop $extensions $key $extension} + + + + + + + {/loop} +
    内存接口PHP 扩展环境Config 设置
    {$key} + {if $extension['support']} + 支持 + {else} + 不支持 + {/if} + + {if $extension['status']} + 已开启 + {else} + 未开启 + {/if} + {if $key == 'opcache' && $extensions['eAccelerator']['status'] && $extensions['opcache']['status']} + eAccelerator 不可与 opcache同时开启 + {/if} + + {if $extension['status'] && $extension['clear']} + {$extension['clear']['title']} + {/if} + {$extension['extra']} +
    +
    +
    +
    +{template 'common/footer'} diff --git a/web/themes/default/user/post.html b/web/themes/default/user/post.html new file mode 100644 index 0000000..2d87a76 --- /dev/null +++ b/web/themes/default/user/post.html @@ -0,0 +1,89 @@ +{template 'common/header'} +
    + + +
    + +
    + +
    + +
    + + {if $is_used != 'used'} +
    + 用户名已经被注册! + 用户名不能为空! + 用户名必须为 3 到 30 个字符组成,包括汉字,大小写字母(不区分大小写) +
    + {/if} + + {if $is_used == 'used'} +
    不是系统用户
    + {/if} +
    +
    + + {if $is_used != 'used'} + +
    + +
    + + +
    请填写密码,最小长度为 8 个字符
    +
    +
    + + + +
    + +
    + +
    重复输入密码,确认正确输入
    +
    +
    + + {/if} + + +
    + +
    + +
    +
    + +
    + + +
    + +
    +
    +
    + + +{template 'common/footer'} + diff --git a/web/themes/default/user/profile.html b/web/themes/default/user/profile.html new file mode 100644 index 0000000..26f7546 --- /dev/null +++ b/web/themes/default/user/profile.html @@ -0,0 +1,347 @@ +{template 'common/header'} +
    + {if $_W['highest_role'] != 'founder'} +
    + +
    +

    +
    +
    + {/if} + {if $user_type=='' || $user_type == PERSONAL_BASE_TYPE} +
    + + + + + + + + + + + + + + + + + + + + + + + +
    账户设置
    头像
    用户{if permission_check_account_user('see_user_profile_edit_username')}{/if}
    密码******
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {if $_W['isadmin']} + + + + + + {/if} +
    基础信息
    真实姓名
    上次登录时间
    上次登录IP
    注册时间
    到期时间{$endtime}
    备注
    + + + {/if} + +
    + + +{if $user_type == PERSONAL_BIND_TYPE} + + + +{/if} +{template 'common/footer'} \ No newline at end of file