diff options
author | matt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105> | 2008-01-12 04:10:43 +0300 |
---|---|---|
committer | matt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105> | 2008-01-12 04:10:43 +0300 |
commit | a2f0e87dc6d4d14507518bf34f22773387356529 (patch) | |
tree | 8035dbde57e7a52101a732c1a66afed588161f77 | |
parent | 506ecb7c354b623f04b7700e0c485bd46e1d9255 (diff) |
- added links to admin modules in the UI
- added new module displayJavascriptCode
- php renderer now renders a flat version of the datatable for more convenience
- XML/JSON/CSV have a simple output now :-)
- added automatic conversion of know php data structures into DataTable so any API returning not-so-complex data structure can automatically benefit from DataTable power and get the output in XML/JSON/CSV/HTML/PHP etc.
- added a nice helper page that lists all API methods, + links to examples
- did test all API calls with all formats. seems to work good. had to fix a looooot of problems but im happy with the final result :-)
enjoy!!!
24 files changed, 471 insertions, 95 deletions
diff --git a/config/global.ini.php b/config/global.ini.php index 9e7f5b01b0..7e4e842f52 100755 --- a/config/global.ini.php +++ b/config/global.ini.php @@ -26,9 +26,6 @@ current = en default = en [Plugins] -enabled[] = Login -enabled[] = UsersManager -enabled[] = SitesManager enabled[] = UserSettings enabled[] = VisitsSummary @@ -40,6 +37,10 @@ enabled[] = VisitFrequency enabled[] = VisitTime enabled[] = VisitorInterest enabled[] = ExamplePlugin +
+enabled[] = Login
+enabled[] = UsersManager
+enabled[] = SitesManager
;enabled[] = Openads enabled[] = Installation diff --git a/modules/API/Proxy.php b/modules/API/Proxy.php index 3644404893..8d815ecefe 100755 --- a/modules/API/Proxy.php +++ b/modules/API/Proxy.php @@ -122,21 +122,97 @@ class Piwik_API_Proxy } $this->alreadyRegistered[$fileName] = true; + }
+
+ // Piwik_moduleName_API => moduleName
+ protected function getModuleNameFromClassName( $className )
+ {
+ $start = strpos($className, '_') + 1;
+ return substr($className, $start , strrpos($className, '_') - $start);
+ } + // return false when not possible
+ public function getExampleUrl($class, $methodName)
+ {
+ $knowExampleDefaultParametersValues = array(
+ 'access' => 'view',
+ 'idSite' => '1',
+ 'userLogin' => 'test',
+ 'password' => 'passwordExample',
+ 'email' => 'test@example.org',
+
+ 'siteName' => 'new example website',
+ 'urls' => 'http://example.org', // used in addSite, updateSite
+
+ 'period' => 'day',
+ 'date' => 'today',
+ );
+
+ $doNotPrintExampleForTheseMethods = array(
+ 'deleteSite',
+ 'deleteUser',
+ );
+
+ if(in_array($methodName,$doNotPrintExampleForTheseMethods))
+ {
+ return false;
+ }
+ // we try to give an URL example to call the API
+ $aParameters = $this->getParametersList($class, $methodName);
+ $moduleName = $this->getModuleNameFromClassName($class);
+ $urlExample = '?module=API&method='.$moduleName.'.'.$methodName.'&';
+ foreach($aParameters as $nameVariable=> $defaultValue)
+ {
+ // there is NO default value we need an example value or we can't generate the example
+ if($defaultValue === Piwik_API_Proxy::NO_DEFAULT_VALUE)
+ {
+ if(isset($knowExampleDefaultParametersValues[$nameVariable]))
+ {
+ $exampleValue = $knowExampleDefaultParametersValues[$nameVariable];
+ $urlExample .= $nameVariable . '=' . $exampleValue . '&';
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ }
+
+ return substr($urlExample,0,-1);
} - public function getAllInterfaceString() { $str = ''; foreach($this->api as $class => $info) - { - $str .= "\n<br>" . "List of the public methods for the class ".$class; + {
+ $moduleName = $this->getModuleNameFromClassName($class); + $str .= "\n<h2>Module ".$moduleName."</h2>"; foreach($info as $methodName => $infoMethod) - { + {
+
+ $exampleUrl = $this->getExampleUrl($class, $methodName);
+ $params = $this->getStrListParameters($class, $methodName); - $str .= "\n<br>" . "- $methodName : " . $params; + $str .= "\n" . "- <b>$methodName " . $params . "</b>";
+
+ $str .= '<small>';
+ if($exampleUrl !== false)
+ {
+ $str .= " [ Example in
+ <a target=_blank href='$exampleUrl&format=xml'>XML</a>,
+ <a target=_blank href='$exampleUrl&format=PHP'>PHP</a>,
+ <a target=_blank href='$exampleUrl&format=JSON'>Json</a>,
+ <a target=_blank href='$exampleUrl&format=CSV'>Csv</a>
+ ]";
+ }
+ else
+ {
+ $str .= " [ No example available ]";
+ }
+ $str .= '</small>';
+ $str .= "\n<br>"; } - $str.="\n<br>"; } return $str; } @@ -156,12 +232,12 @@ class Piwik_API_Proxy $str = $nameVariable; if($defaultValue !== Piwik_API_Proxy::NO_DEFAULT_VALUE) { - $str .= " = $defaultValue"; + $str .= " = '$defaultValue'"; } $asParameters[] = $str; } $sParameters = implode(", ", $asParameters); - return "[$sParameters]"; + return "($sParameters)"; } /** @@ -268,7 +344,7 @@ class Piwik_API_Proxy assert(!is_null(self::$classCalled)); $this->registerClass(self::$classCalled); - + $className = $this->getClassNameFromModule(self::$classCalled); // instanciate the object diff --git a/modules/API/Request.php b/modules/API/Request.php index 6cea379ef4..05705ae0a5 100644 --- a/modules/API/Request.php +++ b/modules/API/Request.php @@ -79,10 +79,13 @@ class Piwik_API_Request public function process() { try { - + // read the format requested for the output data + $outputFormatRequested = Piwik_Common::getRequestVar('format', 'xml', 'string', $this->requestToUse);
+ $outputFormatRequested = strtolower($outputFormatRequested);
+
// read parameters $moduleMethod = Piwik_Common::getRequestVar('method', null, null, $this->requestToUse); - +
list($module, $method) = $this->extractModuleAndMethod($moduleMethod); if(!Piwik_PluginsManager::getInstance()->isPluginEnabled($module)) @@ -133,27 +136,71 @@ class Piwik_API_Request $this->applyDataTableGenericFilters($dataTable);
- $dataTable->applyQueuedFilters(); + $dataTable->applyQueuedFilters();
+ $toReturn = $this->getRenderedDataTable($dataTable); - } - elseif(!is_array($toReturn) // an empty array is not considered as "nothing has been returned" - && empty($toReturn)) + }
+
+ // Case nothing returned (really nothing was 'return'ed),
+ // => the operation was successful + elseif(!isset($toReturn)) { - $format = Piwik_Common::getRequestVar('format', 'xml', 'string', $this->requestToUse); - $toReturn = $this->getStandardSuccessOutput($format); + $toReturn = $this->getStandardSuccessOutput($outputFormatRequested); + }
+
+ // Case an array is returned from the API call, we convert it to the requested format
+ // - if calling from inside the application (format = original)
+ // => the data stays unchanged (ie. a standard php array or whatever data structure)
+ // - if any other format is requested, we have to convert this data structure (which we assume
+ // to be an array) to a DataTable in order to apply the requested DataTable_Renderer (for example XML)
+ elseif(is_array($toReturn))
+ {
+ if($outputFormatRequested == 'original')
+ {
+ // we handle the serialization. Because some php array have a very special structure that
+ // couldn't be converted with the automatic DataTable->loadFromSimpleArray
+ // the user may want to request the original PHP data structure serialized by the API
+ // in case he has to setup serialize=1 in the URL
+ if($this->caseRendererPHPSerialize( $defaultSerialize = 0))
+ {
+ $toReturn = serialize($toReturn);
+ }
+ }
+ else
+ {
+// var_dump($toReturn);exit;
+// echo "$outputFormatRequested requested";
+ $dataTable = new Piwik_DataTable();
+ $dataTable->loadFromSimpleArray($toReturn);
+// echo $dataTable;exit;
+ $toReturn = $this->getRenderedDataTable($dataTable);
+// echo $toReturn;exit;
+ }
+ }
+ // bool // integer // float // anything else would'nt work and is not handled (objects!)
+ else
+ {
+ if( $toReturn === true )
+ {
+ $toReturn = 'true';
+ }
+ elseif( $toReturn === false )
+ {
+ $toReturn = 'false';
+ }
+ return $this->getStandardSuccessOutput($outputFormatRequested, $message = $toReturn);
} } catch(Exception $e ) { - $format = Piwik_Common::getRequestVar('format', 'xml', 'string', $this->requestToUse); // if it is not a direct API call, we are requesting the original data structure // and we actually are handling this exception at the top level in the FrontController - if($format == 'original') + if($outputFormatRequested == 'original') { throw $e; } - $toReturn = $this->getExceptionOutput( $e->getMessage(), $format); + $toReturn = $this->getExceptionOutput( $e->getMessage(), $outputFormatRequested); } @@ -161,9 +208,8 @@ class Piwik_API_Request } - function getStandardSuccessOutput($format) + function getStandardSuccessOutput($format, $message = 'ok') { - $return = 'TO OVERWRITE! getStandardSuccessOutput()'; switch($format) { case 'xml': @@ -171,22 +217,29 @@ class Piwik_API_Request $return = '<?xml version="1.0" encoding="utf-8" ?>'. '<result>'. - ' <success message="ok" />'. + ' <success message="'.$message.'" />'. '</result>'; break; case 'json': @header( "Content-type: application/json" ); - $return = '{"result":"success", "message":"ok"}'; + $return = '{"result":"success", "message":"'.$message.'"}'; break; case 'php': - $return = array('result' => 'success', 'message' => 'ok'); + $return = array('result' => 'success', 'message' => $message); if($this->caseRendererPHPSerialize()) { $return = serialize($return); } - break; + break;
+
+ case 'csv':
+ header("Content-type: application/vnd.ms-excel");
+ header("Content-Disposition: attachment; filename=piwik-report-export.csv");
+ $return = "message\n".$message;
+ break;
+ default: - $return = 'Success:ok'; + $return = 'Success:'.$message; break; } @@ -194,7 +247,6 @@ class Piwik_API_Request } function getExceptionOutput($message, $format) { - $return = 'TO OVERWRITE! getExceptionOutput()'; switch($format) { case 'xml': @@ -232,6 +284,7 @@ class Piwik_API_Request { // Renderer $format = Piwik_Common::getRequestVar('format', 'php', 'string', $this->requestToUse); + $format = strtolower($format);
// if asked for original dataStructure if($format == 'original') @@ -241,6 +294,14 @@ class Piwik_API_Request && $dataTable->getRowsCount() == 1) { return $dataTable->getRowFromId(0)->getColumn('value'); + }
+
+ // the original data structure can be asked as serialized.
+ // but by default it's not serialized
+ if($this->caseRendererPHPSerialize( $defaultSerialize = 0))
+ {
+// var_export($dataTable);exit;
+ $dataTable = serialize($dataTable);
} return $dataTable; } @@ -258,9 +319,9 @@ class Piwik_API_Request } - function caseRendererPHPSerialize() + function caseRendererPHPSerialize($defaultSerializeValue = 1) { - $serialize = Piwik_Common::getRequestVar('serialize', 1, 'int', $this->requestToUse); + $serialize = Piwik_Common::getRequestVar('serialize', $defaultSerializeValue, 'int', $this->requestToUse); if($serialize) { return true; diff --git a/modules/DataTable.php b/modules/DataTable.php index 75fd42ef78..173f19003c 100644 --- a/modules/DataTable.php +++ b/modules/DataTable.php @@ -479,11 +479,18 @@ class Piwik_DataTable * Load the data from a PHP array * * @param array Array with the following structure - * array( - * array(...), // row1 - * array(...), // row2 - * ) - * ) + * array(
+ * // row1 + * array(
+ * Piwik_DataTable_Row::COLUMNS => array( col1_name => value1, col2_name => value2, ...),
+ * Piwik_DataTable_Row::DETAILS => array( detail1_name => value1, ...), // see Piwik_DataTable_Row
+ *
+ * ),
+ *
+ * // row2 + * array( ... ), + * + * ) * * @see DataTable_Row::loadFromArray for the row structures */ @@ -498,6 +505,91 @@ class Piwik_DataTable $this->addRow($row); } + }
+
+ /**
+ * Load the data from a simple php array.
+ * Basically maps a simple multidimensional php php array to a DataTable.
+ * Not recursive (if a row contains a php array itself, it won't work well...)
+ *
+ * @param array Array with the simple structure:
+ * array(
+ * array( col1_name => valueA, col2_name => valueC, ...),
+ * array( col1_name => valueB, col2_name => valueD, ...),
+ * )
+ */
+ public function loadFromSimpleArray( $array )
+ {
+// var_dump($array);exit;
+
+
+ // we define an exception we may throw if at one point we notice that we cannot handle the data structure
+ $e = new Exception(" Data structure returned is not convertible in the requested format.".
+ " Try to call this method with the parameters '&format=original&serialize=1'".
+ "; you will get the original php data structure serialized.".
+ " The data structure looks like this: \n \$data = " . var_export($array, true) . "; ");
+
+
+ // first pass to see if the array has the structure
+ // array(col1_name => val1, col2_name => val2, etc.)
+ // with val* that are never arrays (only strings/numbers/bool/etc.)
+ // if we detect such a "simple" data structure we convert it to a row with the correct columns' names
+ $rowBuilt = array(); $thisIsNotThatSimple = false;
+ foreach($array as $columnName => $columnValue )
+ {
+ if(is_array($columnValue) || is_object($columnValue))
+ {
+ $thisIsNotThatSimple = true;
+ break;
+ }
+ $rowBuilt += array($columnName => $columnValue );
+ }
+ if($thisIsNotThatSimple === false)
+ {
+ $this->addRow( new Piwik_DataTable_Row( array( Piwik_DataTable_Row::COLUMNS => $rowBuilt ) ) );
+ // we have converted our simple array to one single row
+ // => we exit the method as the job is now finished
+ return;
+ }
+
+
+ foreach($array as $key => $row)
+ {
+ // stuff that looks like a line
+ if(is_array($row))
+ {
+ /**
+ * We make sure we can convert this PHP array without losing information.
+ * We are able to convert only simple php array (no strings keys, no sub arrays, etc.)
+ *
+ */
+
+ // if the key is a string it means that some information was contained in this key.
+ // it cannot be lost during the conversion. Because we are not able to handle properly
+ // this key, we throw an explicit exception.
+ if(is_string($key))
+ {
+ throw $e;
+ }
+ // if any of the sub elements of row is an array we cannot handle this data structure...
+ foreach($row as $subRow)
+ {
+ if(is_array($subRow))
+ {
+ throw $e;
+ }
+ }
+
+
+ $row = new Piwik_DataTable_Row( array( Piwik_DataTable_Row::COLUMNS => $row ) );
+ }
+ // other (string, numbers...) => we build a line from this value
+ else
+ {
+ $row = new Piwik_DataTable_Row( array( Piwik_DataTable_Row::COLUMNS => array($key => $row)) );
+ }
+ $this->addRow($row);
+ }
} /** diff --git a/modules/DataTable/Renderer/Csv.php b/modules/DataTable/Renderer/Csv.php index b8bc98ac0b..4e7a7e4e9c 100644 --- a/modules/DataTable/Renderer/Csv.php +++ b/modules/DataTable/Renderer/Csv.php @@ -17,7 +17,8 @@ * If the text contains an embedded delimiter string or qualifier string, the text qualifier is placed around the text, and the embedded qualifier strings are doubled. * Formatting and layout are ignored. */ -require_once "DataTable/Renderer/Php.php"; +require_once "DataTable/Renderer/Php.php";
+ class Piwik_DataTable_Renderer_Csv extends Piwik_DataTable_Renderer { public $separator = ','; @@ -95,8 +96,20 @@ class Piwik_DataTable_Renderer_Csv extends Piwik_DataTable_Renderer } } // var_dump($csv);exit; - $str = ''; - $str .= implode($this->separator, array_keys($allColumns)); + $str = '';
+
+
+ // specific case, we have only one column and this column wasn't named properly (indexed by a number)
+ // we don't print anything in the CSV file => an empty line
+ if(sizeof($allColumns) == 1 && reset($allColumns) && !is_string(key($allColumns)) )
+ {
+ $str .= '';
+ }
+ else
+ { + $str .= implode($this->separator, array_keys($allColumns));
+ }
+ // we render the CSV foreach($csv as $theRow) { diff --git a/modules/DataTable/Renderer/Json.php b/modules/DataTable/Renderer/Json.php index 33bba28eb7..d3a0d92ba9 100644 --- a/modules/DataTable/Renderer/Json.php +++ b/modules/DataTable/Renderer/Json.php @@ -22,7 +22,8 @@ class Piwik_DataTable_Renderer_Json extends Piwik_DataTable_Renderer protected function renderTable($table) { $renderer = new Piwik_DataTable_Renderer_Php($table, $serialize = false); - $array = $renderer->render(); + $array = $renderer->flatRender();
+
$str = json_encode($array); return $str; } diff --git a/modules/DataTable/Renderer/Php.php b/modules/DataTable/Renderer/Php.php index c50dce64f1..90540b72b8 100644 --- a/modules/DataTable/Renderer/Php.php +++ b/modules/DataTable/Renderer/Php.php @@ -2,26 +2,27 @@ /** * Returns the equivalent PHP array of the DataTable. - * You can specify in the constructor if you want the serialized version. + * You can specify in the constructor if you want the serialized version.
+ * Please note that by default it will produce a flat version of the array.
+ * See the method flatRender() for details. * * @package Piwik_DataTable * @subpackage Piwik_DataTable_Renderer */ class Piwik_DataTable_Renderer_Php extends Piwik_DataTable_Renderer { - protected $serialize; - function __construct($table = null, $serialize = true) + public function __construct($table = null, $serialize = true) { parent::__construct($table); $this->setSerialize($serialize); } - function setSerialize( $bool ) + public function setSerialize( $bool ) { $this->serialize = $bool; } - function __toString() + public function __toString() { $data = $this->render(); if(!is_string($data)) @@ -30,8 +31,60 @@ class Piwik_DataTable_Renderer_Php extends Piwik_DataTable_Renderer } return $data; } +
+ /**
+ * Produces a flat php array from the DataTable, putting "columns" and "details" on the same level.
+ *
+ * For example, when a originalRender() would be
+ * array( 'columns' => array( 'col1_name' => value1, 'col2_name' => value2 ),
+ * 'details' => array( 'detail1_name' => value_detail) )
+ *
+ * a flatRender() is
+ * array( 'col1_name' => value1,
+ * 'col2_name' => value2,
+ * 'detail1_name' => value_detail )
+ *
+ * @return array Php array representing the 'flat' version of the datatable
+ *
+ */
+ public function flatRender()
+ {
+ // A DataTable_Simple is already flattened so no need to do some crazy stuff to convert it
+ if($this->table instanceof Piwik_DataTable_Simple)
+ {
+ $flatArray = $this->renderSimpleTable($this->table);
+ }
+ // A normal DataTable needs to be handled specifically
+ else
+ {
+ $array = $this->renderTable($this->table);
+ $flatArray = array();
+ foreach($array as $row)
+ {
+ $newRow = $row['columns'] + $row['details'];
+ if(isset($row['idsubdatatable']))
+ {
+ $newRow += array('idsubdatatable' => $row['idsubdatatable']);
+ }
+ $flatArray[] = $newRow;
+ }
+ }
+
+ if($this->serialize)
+ {
+ $flatArray = serialize($flatArray);
+ }
+
+ return $flatArray;
+ }
+
+ public function render()
+ {
+ $toReturn = $this->flatRender();
+ return $toReturn;
+ }
- function render() + public function originalRender() { if($this->table instanceof Piwik_DataTable_Simple) { @@ -49,6 +102,9 @@ class Piwik_DataTable_Renderer_Php extends Piwik_DataTable_Renderer return $array; } +
+ protected $serialize;
+
protected function renderTable($table) { diff --git a/modules/DataTable/Renderer/Xml.php b/modules/DataTable/Renderer/Xml.php index cb71476137..1c1e680a0f 100644 --- a/modules/DataTable/Renderer/Xml.php +++ b/modules/DataTable/Renderer/Xml.php @@ -21,10 +21,13 @@ class Piwik_DataTable_Renderer_Xml extends Piwik_DataTable_Renderer } protected function renderTable($table) - { + {
+// echo $table;exit; $renderer = new Piwik_DataTable_Renderer_Php($table, $serialize = false); - $array = $renderer->render(); - + $array = $renderer->flatRender(); +
+// var_dump($array); exit;
+ require_once 'XML/Serializer.php'; $options = array( diff --git a/modules/Piwik.php b/modules/Piwik.php index bdd2910539..42d1bf04c7 100755 --- a/modules/Piwik.php +++ b/modules/Piwik.php @@ -95,6 +95,15 @@ class Piwik return $resultCheck; } + static public function getJavascriptCode($idSite, $piwikUrl, $actionName = "''")
+ {
+ $jsTag = file_get_contents( PIWIK_INCLUDE_PATH . "/modules/LogStats/javascriptTag.tpl");
+ $jsTag = nl2br(htmlentities($jsTag));
+ $jsTag = str_replace('{$actionName}', "''", $jsTag);
+ $jsTag = str_replace('{$idSite}', $idSite, $jsTag);
+ $jsTag = str_replace('{$piwikUrl}', $piwikUrl, $jsTag);
+ return $jsTag;
+ }
static public function getMemoryLimitValue() { diff --git a/modules/ViewDataTable/Html.php b/modules/ViewDataTable/Html.php index 8fb6306b63..fbf821bfcc 100644 --- a/modules/ViewDataTable/Html.php +++ b/modules/ViewDataTable/Html.php @@ -69,7 +69,9 @@ class Piwik_ViewDataTable_Html extends Piwik_ViewDataTable $renderer = Piwik_DataTable_Renderer::factory('php');
$renderer->setTable($this->dataTable);
$renderer->setSerialize( false );
- $phpArray = $renderer->render();
+ // we get the php array from the datatable
+ // but conserving the original datatable format, which means rows 'columns', 'details' and 'idsubdatatable'
+ $phpArray = $renderer->originalRender();
return $phpArray;
}
diff --git a/plugins/API/Controller.php b/plugins/API/Controller.php index 43dee711b7..aa22304503 100644 --- a/plugins/API/Controller.php +++ b/plugins/API/Controller.php @@ -11,8 +11,14 @@ class Piwik_API_Controller extends Piwik_Controller } function listAllAPI() - { - echo "<h1>List of all modules API</h1>"; + {
+//?module=API&method=Referers.getKeywords&idSite=1&period=month&date=today&format=xml
+//
+//or yesterday visits information in JSON
+//?module=API&method=VisitsSummary.get&idSite=1&period=month&date=yesterday&format=json + echo "<style>body{ font-family:georgia,arial; font-size:0.95em;} </style>";
+ echo "<h1>API quick documentation</h1>";
+ echo "<p>If you don't have data for today you can first <a href='misc/generateVisits.php' target=_blank>generate some data</a> using the Visits Generator script.</p>"; $errors = ''; $plugins = Piwik_PluginsManager::getInstance()->getLoadedPluginsName(); diff --git a/plugins/Home/templates/cloud.tpl b/plugins/Home/templates/cloud.tpl index 31e556bfde..744d558ebc 100644 --- a/plugins/Home/templates/cloud.tpl +++ b/plugins/Home/templates/cloud.tpl @@ -58,8 +58,7 @@ span.size6, span.size6 a { {if false !== $labelDetails[$value.word].url}<a href="{$labelDetails[$value.word].url}" target="_blank">{/if} {if false !== $labelDetails[$value.word].logo}<img src="{$labelDetails[$value.word].logo}" width="{$value.logoWidth}">{else} - {$value.wordTruncated}{/if}{if false !== $labelDetails[$value.word].url}</a>{/if} - </span> + {$value.wordTruncated}{/if}{if false !== $labelDetails[$value.word].url}</a>{/if}</span> {/foreach} {/if} {include file="Home/templates/datatable_footer.tpl"} diff --git a/plugins/Home/templates/index.tpl b/plugins/Home/templates/index.tpl index e94a25e843..a4302ad022 100644 --- a/plugins/Home/templates/index.tpl +++ b/plugins/Home/templates/index.tpl @@ -87,6 +87,11 @@ tr td.label img.plusMinus { margin:10px; } +#miscLinks{ + font-size:small; + padding-right:20px; +} + #sitesSelection { } @@ -158,6 +163,7 @@ tr td.label img.plusMinus { <p>User logged = {$userLogin}</p> {include file="Home/templates/period_select.tpl"}<br><br> {include file="Home/templates/sites_select.tpl"}<br> + {include file="Home/templates/links_misc_modules.tpl"}<br> </div> </div> diff --git a/plugins/Home/templates/links_misc_modules.tpl b/plugins/Home/templates/links_misc_modules.tpl new file mode 100644 index 0000000000..c21080836e --- /dev/null +++ b/plugins/Home/templates/links_misc_modules.tpl @@ -0,0 +1,8 @@ +<span id="miscLinks">
+ <p>Links to other modules:</p>
+ <ul>
+ <li>Manage: <a href='?module=SitesManager'>Sites</a> - <a href='?module=UsersManager'>Users</a></li>
+ <li><a href='?module=Login'>Login</a> - <a href='?module=Logout'>Logout</a></a></li>
+ <li>Discover the power of the Piwik API!!! <br><a href='?module=API&action=listAllAPI'>API methods list</a></li>
+ </ul>
+</div>
\ No newline at end of file diff --git a/plugins/Installation/Controller.php b/plugins/Installation/Controller.php index b81ac78eb0..fe58e495dd 100644 --- a/plugins/Installation/Controller.php +++ b/plugins/Installation/Controller.php @@ -279,12 +279,8 @@ class Piwik_Installation_Controller extends Piwik_Controller $view->websiteName = $_SESSION['site_name']; - - $jsTag = file_get_contents( PIWIK_INCLUDE_PATH . "/modules/LogStats/javascriptTag.tpl"); - $jsTag = nl2br(htmlentities($jsTag)); - $jsTag = str_replace('{$actionName}', "''", $jsTag); - $jsTag = str_replace('{$idSite}', $_SESSION['site_idSite'], $jsTag); - $jsTag = str_replace('{$piwikUrl}', Piwik_Url::getCurrentUrlWithoutFileName(), $jsTag); +
+ $jsTag = Piwik::getJavascriptCode($_SESSION['site_idSite'], Piwik_Url::getCurrentUrlWithoutFileName());
$view->javascriptTag = $jsTag; $view->showNextStep = true; diff --git a/plugins/SitesManager/API.php b/plugins/SitesManager/API.php index c8f52cb7cd..5d0b68eef8 100755 --- a/plugins/SitesManager/API.php +++ b/plugins/SitesManager/API.php @@ -59,12 +59,12 @@ class Piwik_SitesManager_API extends Piwik_Apiable * @exception if the website ID doesn't exist or the user doesn't have access to it * @return array list of URLs */ - static public function getSiteUrlsFromId( $idsite ) + static public function getSiteUrlsFromId( $idSite ) { - Piwik::checkUserHasViewAccess($idsite); + Piwik::checkUserHasViewAccess($idSite); - $site = self::getSiteFromId($idsite); - $urls = self::getAliasSiteUrlsFromId($idsite); + $site = self::getSiteFromId($idSite); + $urls = self::getAliasSiteUrlsFromId($idSite); return array_merge(array($site['main_url']), $urls); } @@ -197,11 +197,11 @@ class Piwik_SitesManager_API extends Piwik_Apiable * * @return int the website ID created */ - static public function addSite( $name, $urls ) + static public function addSite( $siteName, $urls ) { Piwik::checkUserIsSuperUser(); - self::checkName($name); + self::checkName($siteName); $urls = self::cleanParameterUrls($urls); self::checkUrls($urls); self::checkAtLeastOneUrl($urls); @@ -212,7 +212,7 @@ class Piwik_SitesManager_API extends Piwik_Apiable $urls = array_slice($urls, 1); $db->insert(Piwik::prefixTable("site"), array( - 'name' => $name, + 'name' => $siteName, 'main_url' => $url, ) ); @@ -270,16 +270,16 @@ class Piwik_SitesManager_API extends Piwik_Apiable * * @return int the number of inserted URLs */ - static public function addSiteAliasUrls( $idsite, $urls) + static public function addSiteAliasUrls( $idSite, $urls) { - Piwik::checkUserHasAdminAccess( $idsite ); + Piwik::checkUserHasAdminAccess( $idSite ); $urls = self::cleanParameterUrls($urls); self::checkUrls($urls); - $urlsInit = self::getSiteUrlsFromId($idsite); + $urlsInit = self::getSiteUrlsFromId($idSite); $toInsert = array_diff($urls, $urlsInit); - self::insertSiteUrls($idsite, $toInsert); + self::insertSiteUrls($idSite, $toInsert); return count($toInsert); } @@ -332,11 +332,11 @@ class Piwik_SitesManager_API extends Piwik_Apiable * * @return bool true on success */ - static public function updateSite( $idSite, $name, $urls = null) + static public function updateSite( $idSite, $siteName, $urls = null) { Piwik::checkUserHasAdminAccess($idSite); - self::checkName($name); + self::checkName($siteName); // SQL fields to update $bind = array(); @@ -351,7 +351,7 @@ class Piwik_SitesManager_API extends Piwik_Apiable $bind['main_url'] = $url; } - $bind['name'] = $name; + $bind['name'] = $siteName; $db = Zend_Registry::get('db'); @@ -366,7 +366,8 @@ class Piwik_SitesManager_API extends Piwik_Apiable if(count($urls) > 1) { self::replaceSiteUrls($idSite, $urls); - } + }
+ } /** @@ -430,9 +431,9 @@ class Piwik_SitesManager_API extends Piwik_Apiable * * @exception if the website name is empty */ - static private function checkName($name) + static private function checkName($siteName) { - if(empty($name)) + if(empty($siteName)) { throw new Exception("The site name can't be empty."); } diff --git a/plugins/SitesManager/Controller.php b/plugins/SitesManager/Controller.php index abd8455a34..239445d726 100644 --- a/plugins/SitesManager/Controller.php +++ b/plugins/SitesManager/Controller.php @@ -13,5 +13,15 @@ class Piwik_SitesManager_Controller extends Piwik_Controller // var_dump($sites);exit; $view->sites = $sites; echo $view->render(); + }
+
+ function displayJavascriptCode()
+ {
+ $jsTag = Piwik::getJavascriptCode(Piwik_Common::getRequestVar('idsite',1), Piwik_Url::getCurrentUrlWithoutFileName());
+
+ $view = new Piwik_View('SitesManager/templates/DisplayJavascriptCode.tpl');
+ $view->jsTag = $jsTag;
+
+ echo $view->render();
} }
\ No newline at end of file diff --git a/plugins/SitesManager/templates/DisplayJavascriptCode.tpl b/plugins/SitesManager/templates/DisplayJavascriptCode.tpl new file mode 100644 index 0000000000..9151ba7103 --- /dev/null +++ b/plugins/SitesManager/templates/DisplayJavascriptCode.tpl @@ -0,0 +1,7 @@ +<p>Here is the javascript code to include on all your pages:</p>
+
+<code>
+{$jsTag}
+</code>
+
+<p><a href='index.php'>Back to Piwik homepage</a></p>
\ No newline at end of file diff --git a/plugins/SitesManager/templates/SitesManager.js b/plugins/SitesManager/templates/SitesManager.js index 5363ba2fe2..8fdf9c74a4 100644 --- a/plugins/SitesManager/templates/SitesManager.js +++ b/plugins/SitesManager/templates/SitesManager.js @@ -1,5 +1,5 @@ -function getDeleteSiteAJAX( idsite ) +function getDeleteSiteAJAX( idSite ) { var ajaxRequest = getStandardAjaxConf(); toggleAjaxLoading(); @@ -9,7 +9,7 @@ function getDeleteSiteAJAX( idsite ) parameters.module = 'API'; parameters.format = 'json'; parameters.method = 'SitesManager.deleteSite'; - parameters.idSite = idsite; + parameters.idSite = idSite; ajaxRequest.data = parameters; @@ -24,7 +24,7 @@ function getAddSiteAJAX( row ) // prepare the API parameters to add the user var parameters = new Object; - var name = $(row).find('input[@id=siteadd_name]').val(); + var siteName = $(row).find('input[@id=siteadd_name]').val(); var urls = $(row).find('textarea[@id=siteadd_urls]').val(); var urls = urls.trim().split("\n"); @@ -32,7 +32,7 @@ function getAddSiteAJAX( row ) request += '&module=API'; request += '&format=json'; request += '&method=SitesManager.addSite'; - request += '&name='+escape(name); + request += '&siteName='+escape(siteName); $.each(urls, function (key,value){ request+= '&urls[]='+escape(value);} ); @@ -46,7 +46,7 @@ function getUpdateSiteAJAX( row ) var ajaxRequest = getStandardAjaxConf(); toggleAjaxLoading(); - var name = $(row).find('input[@id=name]').val(); + var siteName = $(row).find('input[@id=siteName]').val(); var idSite = $(row).children('#idSite').html(); var urls = $(row).find('textarea[@id=urls]').val().trim().split("\n"); @@ -54,7 +54,7 @@ function getUpdateSiteAJAX( row ) request += '&module=API'; request += '&format=json'; request += '&method=SitesManager.updateSite'; - request += '&name='+escape(name); + request += '&siteName='+escape(siteName); request += '&idSite='+idSite; $.each(urls, function (key,value){ if(value.length>1) request+= '&urls[]='+value;} ); @@ -93,7 +93,7 @@ function getUpdateSiteAJAX( row ) $('.deleteSite').click( function() { ajaxHideError(); var idRow = $(this).attr('id'); - var nameToDelete = $(this).parent().parent().find('#name').html(); + var nameToDelete = $(this).parent().parent().find('#siteName').html(); var idsiteToDelete = $(this).parent().parent().find('#idSite').html(); if(confirm('Are you sure you want to delete the website "'+nameToDelete+'" (idSite = '+idsiteToDelete+')?')) { @@ -116,7 +116,7 @@ function getUpdateSiteAJAX( row ) function (i,n) { var contentBefore = $(n).html(); var idName = $(n).attr('id'); - if(idName == 'name') + if(idName == 'siteName') { var contentAfter = '<input id="'+idName+'" value="'+contentBefore+'" size="10">'; $(n) diff --git a/plugins/SitesManager/templates/SitesManager.tpl b/plugins/SitesManager/templates/SitesManager.tpl index 759025e5d0..f564f3be36 100644 --- a/plugins/SitesManager/templates/SitesManager.tpl +++ b/plugins/SitesManager/templates/SitesManager.tpl @@ -19,16 +19,18 @@ <th>URLs</th> <th> </th> <th> </th> + <th> Javascript code </th> </tr> </thead> <tbody> {foreach from=$sites key=i item=site} <tr id="row{$i}"> <td id="idSite">{$site.idsite}</td> - <td id="name" class="editableSite">{$site.name}</td> + <td id="siteName" class="editableSite">{$site.name}</td> <td id="urls" class="editableSite">{foreach from=$site.alias_urls item=url}{$url}<br>{/foreach}</td> <td><img src='plugins/UsersManager/images/edit.png' class="editSite" id="row{$i}" href='#'></td> <td><img src='plugins/UsersManager/images/remove.png' class="deleteSite" id="row{$i}" value="Delete"></td> + <td><a href='{url action=displayJavascriptCode idsite=$site.idsite}'>Show Code</a></td> </tr> {/foreach} @@ -37,3 +39,6 @@ <div id="addRowSite"><img src='plugins/UsersManager/images/add.png'> <a href="#">Add a new Site</a></div> + + +<p><a href='index.php'>Back to Piwik homepage</a></p> diff --git a/plugins/UsersManager/API.php b/plugins/UsersManager/API.php index 096bc34974..46b28b26ef 100755 --- a/plugins/UsersManager/API.php +++ b/plugins/UsersManager/API.php @@ -168,15 +168,16 @@ class Piwik_UsersManager_API extends Piwik_Apiable * * @return array the user information */ - static public function getUser( $login ) + static public function getUser( $userLogin ) { Piwik::checkUserIsSuperUser(); - self::checkUserExists($login); + self::checkUserExists($userLogin); $db = Zend_Registry::get('db'); $user = $db->fetchRow("SELECT * FROM ".Piwik::prefixTable("user") - ." WHERE login = ?", $login); + ." WHERE login = ?", $userLogin); +// var_dump($user); exit;
return $user; } diff --git a/plugins/UsersManager/templates/UsersManager.tpl b/plugins/UsersManager/templates/UsersManager.tpl index c3872eefa9..9bcd961349 100644 --- a/plugins/UsersManager/templates/UsersManager.tpl +++ b/plugins/UsersManager/templates/UsersManager.tpl @@ -2,7 +2,7 @@ <script type="text/javascript" src="themes/default/common.js"></script> <link rel="stylesheet" href="themes/default/common-admin.css"> -<h2>Access</h2> +<h2>Manage access</h2> <div id="sites"> <form method="get" action="{$formUrl}" id="accessSites"> @@ -49,7 +49,7 @@ <div id="accessUpdated">Done!</div> -<h2>Users</h2> +<h2>Manage users</h2> <div id="ajaxError" style="display:none"></div> <div id="ajaxLoading" style="display:none">Loading... <img src="themes/default/loading.gif"></div> @@ -81,3 +81,5 @@ </table> <div id="addrow"><img src='plugins/UsersManager/images/add.png'> <a href="#">Add a new user</a></div> <script type="text/javascript" src="plugins/UsersManager/templates/UsersManager.js"></script> + +<p><a href='index.php'>Back to Piwik homepage</a></p>
\ No newline at end of file diff --git a/tests/modules/PHP_Related.test.php b/tests/modules/PHP_Related.test.php index 4a8b95f5bc..ff6f45eea1 100644 --- a/tests/modules/PHP_Related.test.php +++ b/tests/modules/PHP_Related.test.php @@ -253,8 +253,30 @@ class Test_PHP_Related extends UnitTestCase $size = round($size/1024/1024,3); //echo "<br>size compressed string = ". $size."mb"; //echo "<br>after compression all sub arrays = ". $timer; + }
+
+ function test_functionReturnNothing()
+ {
+ function givemenothing()
+ {
+ $a = 4;
+ }
+
+ $return = givemenothing();
+
+ $this->assertFalse(isset($return));
+ $this->assertTrue(empty($return));
+ $this->assertTrue(!is_int($return));
+ $this->assertTrue(!is_string($return));
+ $this->assertTrue(!is_bool($return));
+ } +
+ function test_unserializeObject()
+ {
+// $o = new Piwik_DataTable;
+// $o = 'O:15:"Piwik_DataTable":6:{s:7:"�*�rows";a:10:{i:0;O:19:"Piwik_DataTable_Row":1:{s:1:"c";a:3:{i:0;a:12:{s:5:"label";s:6:"/index";s:9:"nb_visits";s:2:"17";s:7:"nb_hits";s:2:"17";s:23:"entry_nb_unique_visitor";s:2:"12";s:15:"entry_nb_visits";s:2:"16";s:16:"entry_nb_actions";s:2:"19";s:22:"entry_sum_visit_length";s:4:"8102";s:18:"entry_bounce_count";s:2:"15";s:22:"exit_nb_unique_visitor";s:2:"12";s:14:"exit_nb_visits";s:2:"16";s:17:"exit_bounce_count";s:2:"15";s:14:"sum_time_spent";s:4:"3292";}i:1;a:0:{}i:3;N;}}i:1;O:36:"Piwik_DataTable_Row_DataTableSummary":1:{s:1:"c";a:3:{i:0;a:12:{s:5:"label";i:1;s:9:"nb_visits";i:7;s:7:"nb_hits";i:7;s:23:"entry_nb_unique_visitor";i:6;s:15:"entry_nb_visits";i:6;s:16:"entry_nb_actions";i:6;s:22:"entry_sum_visit_length";i:60;s:18:"entry_bounce_count";i:6;s:22:"exit_nb_unique_visitor";i:6;s:14:"exit_nb_visits";i:6;s:17:"exit_bounce_count";i:6;s:14:"sum_time_spent";i:2284;}i:1;a:1:{s:18:"databaseSubtableId";i:38;}i:3;i:193;}}i:2;O:36:"Piwik_DataTable_Row_DataTableSummary":1:{s:1:"c";a:3:{i:0;a:11:{s:5:"label";i:9;s:9:"nb_visits";i:6;s:7:"nb_hits";i:6;s:23:"entry_nb_unique_visitor";i:6;s:15:"entry_nb_visits";i:6;s:16:"entry_nb_actions";i:6;s:22:"entry_sum_visit_length";i:60;s:18:"entry_bounce_count";i:6;s:22:"exit_nb_unique_visitor";i:6;s:14:"exit_nb_visits";i:6;s:17:"exit_bounce_count";i:6;}i:1;a:1:{s:18:"databaseSubtableId";i:18;}i:3;i:173;}}i:3;O:36:"Piwik_DataTable_Row_DataTableSummary":1:{s:1:"c";a:3:{i:0;a:11:{s:5:"label";i:3;s:9:"nb_visits";i:6;s:7:"nb_hits";i:6;s:23:"entry_nb_unique_visitor";i:6;s:15:"entry_nb_visits";i:6;s:16:"entry_nb_actions";i:6;s:22:"entry_sum_visit_length";i:60;s:18:"entry_bounce_count";i:6;s:22:"exit_nb_unique_visitor";i:6;s:14:"exit_nb_visits";i:6;s:17:"exit_bounce_count";i:6;}i:1;a:1:{s:18:"databaseSubtableId";i:9;}i:3;i:164;}}i:4;O:36:"Piwik_DataTable_Row_DataTableSummary":1:{s:1:"c";a:3:{i:0;a:12:{s:5:"label";s:1:"f";s:9:"nb_visits";i:6;s:7:"nb_hits";i:6;s:23:"entry_nb_unique_visitor";i:4;s:15:"entry_nb_visits";i:4;s:16:"entry_nb_actions";i:4;s:22:"entry_sum_visit_length";i:40;s:18:"entry_bounce_count";i:4;s:22:"exit_nb_unique_visitor";i:5;s:14:"exit_nb_visits";i:5;s:17:"exit_bounce_count";i:4;s:14:"sum_time_spent";i:2623;}i:1;a:1:{s:18:"databaseSubtableId";i:31;}i:3;i:186;}}i:5;O:19:"Piwik_DataTable_Row":1:{s:1:"c";a:3:{i:0;a:11:{s:5:"label";s:2:"/9";s:9:"nb_visits";s:1:"5";s:7:"nb_hits";s:1:"5";s:23:"entry_nb_unique_visitor";s:1:"5";s:15:"entry_nb_visits";s:1:"5";s:16:"entry_nb_actions";s:1:"5";s:22:"entry_sum_visit_length";s:2:"50";s:18:"entry_bounce_count";s:1:"5";s:22:"exit_nb_unique_visitor";s:1:"5";s:14:"exit_nb_visits";s:1:"5";s:17:"exit_bounce_count";s:1:"5";}i:1;a:0:{}i:3;N;}}i:6;O:36:"Piwik_DataTable_Row_DataTableSummary":1:{s:1:"c";a:3:{i:0;a:12:{s:5:"label";s:1:"e";s:9:"nb_visits";i:5;s:7:"nb_hits";i:5;s:23:"entry_nb_unique_visitor";i:5;s:15:"entry_nb_visits";i:5;s:16:"entry_nb_actions";i:11;s:22:"entry_sum_visit_length";i:15972;s:18:"entry_bounce_count";i:3;s:22:"exit_nb_unique_visitor";i:3;s:14:"exit_nb_visits";i:3;s:17:"exit_bounce_count";i:3;s:14:"sum_time_spent";i:4711;}i:1;a:1:{s:18:"databaseSubtableId";i:22;}i:3;i:177;}}i:7;O:36:"Piwik_DataTable_Row_DataTableSummary":1:{s:1:"c";a:3:{i:0;a:12:{s:5:"label";s:1:"g";s:9:"nb_visits";i:4;s:7:"nb_hits";i:4;s:23:"entry_nb_unique_visitor";i:4;s:15:"entry_nb_visits";i:4;s:16:"entry_nb_actions";i:5;s:22:"entry_sum_visit_length";i:2267;s:18:"entry_bounce_count";i:3;s:22:"exit_nb_unique_visitor";i:3;s:14:"exit_nb_visits";i:3;s:17:"exit_bounce_count";i:3;s:14:"sum_time_spent";i:2237;}i:1;a:1:{s:18:"databaseSubtableId";i:28;}i:3;i:183;}}i:8;O:19:"Piwik_DataTable_Row":1:{s:1:"c";a:3:{i:0;a:11:{s:5:"label";s:2:"/e";s:9:"nb_visits";s:1:"4";s:7:"nb_hits";s:1:"4";s:23:"entry_nb_unique_visitor";s:1:"3";s:15:"entry_nb_visits";s:1:"3";s:16:"entry_nb_actions";s:1:"3";s:22:"entry_sum_visit_length";s:2:"30";s:18:"entry_bounce_count";s:1:"3";s:22:"exit_nb_unique_visitor";s:1:"4";s:14:"exit_nb_visits";s:1:"4";s:17:"exit_bounce_count";s:1:"3";}i:1;a:0:{}i:3;N;}}i:9;O:19:"Piwik_DataTable_Row":1:{s:1:"c";a:3:{i:0;a:11:{s:5:"label";s:2:"/f";s:9:"nb_visits";s:1:"4";s:7:"nb_hits";s:1:"4";s:23:"entry_nb_unique_visitor";s:1:"4";s:15:"entry_nb_visits";s:1:"4";s:16:"entry_nb_actions";s:1:"4";s:22:"entry_sum_visit_length";s:2:"40";s:18:"entry_bounce_count";s:1:"4";s:22:"exit_nb_unique_visitor";s:1:"4";s:14:"exit_nb_visits";s:1:"4";s:17:"exit_bounce_count";s:1:"4";}i:1;a:0:{}i:3;N;}}}s:12:"�*�currentId";i:163;s:13:"�*�depthLevel";i:0;s:19:"�*�indexNotUpToDate";b:1;s:16:"�*�queuedFilters";a:0:{}s:29:"�*�rowsCountBeforeLimitFilter";i:34;}';
+// $o = unserialize($o);
} - } diff --git a/themes/default/common-admin.css b/themes/default/common-admin.css index dd34c2baf5..72800c6262 100644 --- a/themes/default/common-admin.css +++ b/themes/default/common-admin.css @@ -79,7 +79,6 @@ tbody td, tbody th{ color:#6C8C37; text-decoration:none; font-weight:normal; - background: transparent url(links_yellow.gif) no-repeat 0% 50%; padding-left:15px; } tbody td:hover, tbody th:hover { |