diff --git a/README b/README index ca9123bcbda591c4de4139c5ca8483a3aa2eca57..f78362f2e5b13437bac2b4adfc15b5f2565b9bab 100644 --- a/README +++ b/README @@ -1,3 +1,28 @@ +Install +======= +1- copy paste the javascript code found in log.htm into your website +2- launch index.php -Listing all the plugins API +Some modules +============ +Login +?module=Login + +Logout +?module=Login + +User manager admin UI +?module=UsersManager + +Sites manager admin UI +?module=SitesManager + +All the data is available via APIs for example to get todays keywords in XML +?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 + +You can find the full listing of the APIs provided by the plugins on ?module=API&action=listAllAPI + diff --git a/config/config.ini.php b/config/config.ini.php index 2b9fe1f5d394b4b7c71746ae120e07fea8d2c082..b9cb7b505087ab6a9308cb05fcad902751e91e4a 100755 --- a/config/config.ini.php +++ b/config/config.ini.php @@ -95,7 +95,7 @@ cookie_name = piwik_visitor [log] ; normal messages -;logger_message[] = screen +logger_message[] = screen ;logger_message[] = database ;logger_message[] = file diff --git a/libs/jquery/jquery-calendar.css b/libs/jquery/jquery-calendar.css new file mode 100644 index 0000000000000000000000000000000000000000..2904cac01cca995214cfb8cffd6357bb2d64d839 --- /dev/null +++ b/libs/jquery/jquery-calendar.css @@ -0,0 +1,165 @@ +/* Main Style Sheet for jQuery Calendar */ +#calendar_div, .calendar_inline { + font-family: Arial, Helvetica, sans-serif; + font-size: 14px; + padding: 0; + margin: 0; +} +#calendar_div { + display: none; + border: 1px solid #777; + z-index: 10; /*must have*/ +} +#calendar_div, .calendar_control, .calendar_links, .calendar_header, .calendar { + width: 185px; +} +.calendar_inline { + float: left; + display: block; + border: 0; +} +.calendar_dialog { + padding: 5px !important; + border: 4px ridge #ddd !important; +} +button.calendar_trigger { + width: 25px; +} +img.calendar_trigger { + margin: 2px; + vertical-align: middle; +} +.calendar_prompt { + float: left; + width: 181px; + padding: 2px; + background: #ddd; + color: #000; +} +* html .calendar_prompt { + width: 185px; +} +.calendar_control, .calendar_links, .calendar_header, .calendar { + clear: both; + float: left; + color: #fff; +} +.calendar_control { + background: #400; +} +.calendar_links { + background: #000; +} +.calendar_control, .calendar_links { + font-weight: bold; + font-size: 80%; + letter-spacing: 1px; +} +.calendar_links label { /* disabled links */ + padding: 2px 5px; + color: #888; +} +.calendar_clear, .calendar_prev { + float: left; +} +.calendar_current { + float: left; + width: 35%; + text-align: center; +} +.calendar_close, .calendar_next { + float: right; +} +.calendar_header { + background: #333; + text-align: center; + font-weight: bold; +} +.calendar_header select { + background: #333; + color: #fff; + border: 0px; + font-weight: bold; +} +.calendar { + background: #ccc; + text-align: center; + font-size: 100%; +} +.calendar a { + display: block; + width: 100%; +} +.calendar .calendar_titleRow { + background: #777; +} +.calendar .calendar_daysRow { + background: #eee; + color: #666; +} +.calendar .calendar_daysCell { + color: #000; + border: 1px solid #ddd; +} +#calendar .calendar_daysCell a{ + display: block; +} +.calendar .calendar_weekEndCell { + background: #ddd; +} +.calendar .calendar_daysCellOver { + background: #fff; + border: 1px solid #777; +} +.calendar .calendar_unselectable { + color: #888; +} +.calendar_today { + background: #fcc !important; +} +.calendar_currentDay { + background: #999 !important; +} + +/* ________ CALENDAR LINKS _______ + +** Reset link properties and then override them with !important */ +#calendar_div a, .calendar_inline a { + cursor: pointer; + margin: 0; + padding: 0; + background: none; + color: #000; +} +.calendar_inline .calendar_links a { + padding: 0 5px !important; +} +.calendar_control a, .calendar_links a { + padding: 2px 5px !important; + color: #eee !important; +} +.calendar_titleRow a { + color: #eee !important; +} +.calendar_control a:hover { + background: #fdd !important; + color: #333 !important; +} +.calendar_links a:hover, .calendar_titleRow a:hover { + background: #ddd !important; + color: #333 !important; +} + +/* ___________ IE6 IFRAME FIX ________ */ + +.calendar_cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 193px; /*must have to match width and borders*/ + height: 200px; /*must have to match maximum height*/ +} \ No newline at end of file diff --git a/libs/jquery/jquery-calendar.js b/libs/jquery/jquery-calendar.js new file mode 100644 index 0000000000000000000000000000000000000000..a0a624e091e49f16fa75a3fa67148e7e7fe91734 --- /dev/null +++ b/libs/jquery/jquery-calendar.js @@ -0,0 +1,813 @@ +/* jQuery Calendar v2.7 + Written by Marc Grabanski (m@marcgrabanski.com) and enhanced by Keith Wood (kbwood@iprimus.com.au). + + Copyright (c) 2007 Marc Grabanski (http://marcgrabanski.com/code/jquery-calendar) + Dual licensed under the GPL (http://www.gnu.org/licenses/gpl-3.0.txt) and + CC (http://creativecommons.org/licenses/by/3.0/) licenses. "Share or Remix it but please Attribute the authors." + Date: 09-03-2007 */ + +/* PopUp Calendar manager. + Use the singleton instance of this class, popUpCal, to interact with the calendar. + Settings for (groups of) calendars are maintained in an instance object + (PopUpCalInstance), allowing multiple different settings on the same page. */ +function PopUpCal() { + this._nextId = 0; // Next ID for a calendar instance + this._inst = []; // List of instances indexed by ID + this._curInst = null; // The current instance in use + this._disabledInputs = []; // List of calendar inputs that have been disabled + this._popUpShowing = false; // True if the popup calendar is showing , false if not + this._inDialog = false; // True if showing within a "dialog", false if not + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + clearText: 'Clear', // Display text for clear link + closeText: 'Close', // Display text for close link + prevText: '<Prev', // Display text for previous month link + nextText: 'Next>', // Display text for next month link + currentText: 'Today', // Display text for current month link + dayNames: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Names of days starting at Sunday + monthNames: ['January','February','March','April','May','June', + 'July','August','September','October','November','December'], // Names of months + dateFormat: 'DMY/' // First three are day, month, year in the required order, + // fourth (optional) is the separator, e.g. US would be 'MDY/', ISO would be 'YMD-' + }; + this._defaults = { // Global defaults for all the calendar instances + autoPopUp: 'focus', // 'focus' for popup on focus, + // 'button' for trigger button, or 'both' for either + appendText: '', // Display text following the input box, e.g. showing the format + buttonText: '...', // Text for trigger button + buttonImage: '', // URL for trigger button image + buttonImageOnly: false, // True if the image appears alone, false if it appears on a button + closeAtTop: true, // True to have the clear/close at the top, + // false to have them at the bottom + hideIfNoPrevNext: false, // True to hide next/previous month links + // if not applicable, false to just disable them + changeMonth: true, // True if month can be selected directly, false if only prev/next + changeYear: true, // True if year can be selected directly, false if only prev/next + yearRange: '-10:+10', // Range of years to display in drop-down, + // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn) + firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... + changeFirstDay: true, // True to click on day name to change, false to remain as set + showOtherMonths: false, // True to show dates in other months, false to leave blank + minDate: null, // The earliest selectable date, or null for no limit + maxDate: null, // The latest selectable date, or null for no limit + speed: 'medium', // Speed of display/closure + customDate: null, // Function that takes a date and returns an array with + // [0] = true if selectable, false if not, + // [1] = custom CSS class name(s) or '', e.g. popUpCal.noWeekends + fieldSettings: null, // Function that takes an input field and + // returns a set of custom settings for the calendar + onSelect: null // Define a callback function when a date is selected + }; + $.extend(this._defaults, this.regional['']); + this._calendarDiv = $('<div id="calendar_div"></div>'); + $(document.body).append(this._calendarDiv); + $(document.body).mousedown(this._checkExternalClick); +} + +$.extend(PopUpCal.prototype, { + /* Register a new calendar instance - with custom settings. */ + _register: function(inst) { + var id = this._nextId++; + this._inst[id] = inst; + return id; + }, + + /* Retrieve a particular calendar instance based on its ID. */ + _getInst: function(id) { + return this._inst[id] || id; + }, + + /* Override the default settings for all instances of the calendar. + @param settings object - the new settings to use as defaults (anonymous object) + @return void */ + setDefaults: function(settings) { + $.extend(this._defaults, settings || {}); + }, + + /* Handle keystrokes. */ + _doKeyDown: function(e) { + var inst = popUpCal._getInst(this._calId); + if (popUpCal._popUpShowing) { + switch (e.keyCode) { + case 9: popUpCal.hideCalendar(inst, ''); + break; // hide on tab out + case 13: popUpCal._selectDate(inst); + break; // select the value on enter + case 27: popUpCal.hideCalendar(inst, inst._get('speed')); + break; // hide on escape + case 33: popUpCal._adjustDate(inst, -1, (e.ctrlKey ? 'Y' : 'M')); + break; // previous month/year on page up/+ ctrl + case 34: popUpCal._adjustDate(inst, +1, (e.ctrlKey ? 'Y' : 'M')); + break; // next month/year on page down/+ ctrl + case 35: if (e.ctrlKey) popUpCal._clearDate(inst); + break; // clear on ctrl+end + case 36: if (e.ctrlKey) popUpCal._gotoToday(inst); + break; // current on ctrl+home + case 37: if (e.ctrlKey) popUpCal._adjustDate(inst, -1, 'D'); + break; // -1 day on ctrl+left + case 38: if (e.ctrlKey) popUpCal._adjustDate(inst, -7, 'D'); + break; // -1 week on ctrl+up + case 39: if (e.ctrlKey) popUpCal._adjustDate(inst, +1, 'D'); + break; // +1 day on ctrl+right + case 40: if (e.ctrlKey) popUpCal._adjustDate(inst, +7, 'D'); + break; // +1 week on ctrl+down + } + } + else if (e.keyCode == 36 && e.ctrlKey) { // display the calendar on ctrl+home + popUpCal.showFor(this); + } + }, + + /* Filter entered characters. */ + _doKeyPress: function(e) { + var inst = popUpCal._getInst(this._calId); + var chr = String.fromCharCode(e.charCode == undefined ? e.keyCode : e.charCode); + return (chr < ' ' || chr == inst._get('dateFormat').charAt(3) || + (chr >= '0' && chr <= '9')); // only allow numbers and separator + }, + + /* Attach the calendar to an input field. */ + _connectCalendar: function(target, inst) { + var $input = $(target); + var appendText = inst._get('appendText'); + if (appendText) { + $input.after('<span class="calendar_append">' + appendText + '</span>'); + } + var autoPopUp = inst._get('autoPopUp'); + if (autoPopUp == 'focus' || autoPopUp == 'both') { // pop-up calendar when in the marked field + $input.focus(this.showFor); + } + if (autoPopUp == 'button' || autoPopUp == 'both') { // pop-up calendar when button clicked + var buttonText = inst._get('buttonText'); + var buttonImage = inst._get('buttonImage'); + var buttonImageOnly = inst._get('buttonImageOnly'); + var trigger = $(buttonImageOnly ? '<img class="calendar_trigger" src="' + + buttonImage + '" alt="' + buttonText + '" title="' + buttonText + '"/>' : + '<button type="button" class="calendar_trigger">' + (buttonImage != '' ? + '<img src="' + buttonImage + '" alt="' + buttonText + '" title="' + buttonText + '"/>' : + buttonText) + '</button>'); + $input.wrap('<span class="calendar_wrap"></span>').after(trigger); + trigger.click(this.showFor); + } + $input.keydown(this._doKeyDown).keypress(this._doKeyPress); + $input[0]._calId = inst._id; + }, + + /* Attach an inline calendar to a div. */ + _inlineCalendar: function(target, inst) { + $(target).append(inst._calendarDiv); + target._calId = inst._id; + var date = new Date(); + inst._selectedDay = date.getDate(); + inst._selectedMonth = date.getMonth(); + inst._selectedYear = date.getFullYear(); + popUpCal._adjustDate(inst); + }, + + /* Pop-up the calendar in a "dialog" box. + @param dateText string - the initial date to display (in the current format) + @param onSelect function - the function(dateText) to call when a date is selected + @param settings object - update the dialog calendar instance's settings (anonymous object) + @param pos int[2] - coordinates for the dialog's position within the screen + leave empty for default (screen centre) + @return void */ + dialogCalendar: function(dateText, onSelect, settings, pos) { + var inst = this._dialogInst; // internal instance + if (!inst) { + inst = this._dialogInst = new PopUpCalInstance({}, false); + this._dialogInput = $('<input type="text" size="1" style="position: absolute; top: -100px;"/>'); + this._dialogInput.keydown(this._doKeyDown); + $('body').append(this._dialogInput); + this._dialogInput[0]._calId = inst._id; + } + $.extend(inst._settings, settings || {}); + this._dialogInput.val(dateText); + + /* Cross Browser Positioning */ + if (self.innerHeight) { // all except Explorer + windowWidth = self.innerWidth; + windowHeight = self.innerHeight; + } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode + windowWidth = document.documentElement.clientWidth; + windowHeight = document.documentElement.clientHeight; + } else if (document.body) { // other Explorers + windowWidth = document.body.clientWidth; + windowHeight = document.body.clientHeight; + } + this._pos = pos || // should use actual width/height below + [(windowWidth / 2) - 100, (windowHeight / 2) - 100]; + + // move input on screen for focus, but hidden behind dialog + this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px'); + inst._settings.onSelect = onSelect; + this._inDialog = true; + this._calendarDiv.addClass('calendar_dialog'); + this.showFor(this._dialogInput[0]); + if ($.blockUI) { + $.blockUI(this._calendarDiv); + } + }, + + /* Enable the input field(s) for entry. + @param inputs element/object - single input field or jQuery collection of input fields + @return void */ + enableFor: function(inputs) { + inputs = (inputs.jquery ? inputs : $(inputs)); + inputs.each(function() { + this.disabled = false; + $('../button.calendar_trigger', this).each(function() { this.disabled = false; }); + $('../img.calendar_trigger', +this).css({opacity:'1.0',cursor:''}); + var $this = this; + popUpCal._disabledInputs = $.map(popUpCal._disabledInputs, + function(value) { return (value == $this ? null : value); }); // delete entry + }); + }, + + /* Disable the input field(s) from entry. + @param inputs element/object - single input field or jQuery collection of input fields + @return void */ + disableFor: function(inputs) { + inputs = (inputs.jquery ? inputs : $(inputs)); + inputs.each(function() { + this.disabled = true; + $('../button.calendar_trigger', this).each(function() { this.disabled = true; }); + $('../img.calendar_trigger', this).css({opacity:'0.5',cursor:'default'}); + var $this = this; + popUpCal._disabledInputs = $.map(popUpCal._disabledInputs, + function(value) { return (value == $this ? null : value); }); // delete entry + popUpCal._disabledInputs[popUpCal._disabledInputs.length] = this; + }); + }, + + /* Update the settings for a calendar attached to an input field or division. + @param control element - the input field or div/span attached to the calendar + @param settings object - the new settings to update + @return void */ + reconfigureFor: function(control, settings) { + var inst = this._getInst(control._calId); + if (inst) { + $.extend(inst._settings, settings || {}); + this._updateCalendar(inst); + } + }, + + /* Set the date for a calendar attached to an input field or division. + @param control element - the input field or div/span attached to the calendar + @param date Date - the new date + @return void */ + setDateFor: function(control, date) { + var inst = this._getInst(control._calId); + if (inst) { + inst._setDate(date); + } + }, + + /* Retrieve the date for a calendar attached to an input field or division. + @param control element - the input field or div/span attached to the calendar + @return Date - the current date */ + getDateFor: function(control) { + var inst = this._getInst(control._calId); + return (inst ? inst._getDate() : null); + }, + + /* Pop-up the calendar for a given input field. + @param target element - the input field attached to the calendar + @return void */ + showFor: function(target) { + var input = (target.nodeName && target.nodeName.toLowerCase() == 'input' ? target : this); + if (input.nodeName.toLowerCase() != 'input') { // find from button/image trigger + input = $('input', input.parentNode)[0]; + } + if (popUpCal._lastInput == input) { // already here + return; + } + for (var i = 0; i < popUpCal._disabledInputs.length; i++) { // check not disabled + if (popUpCal._disabledInputs[i] == input) { + return; + } + } + var inst = popUpCal._getInst(input._calId); + popUpCal.hideCalendar(inst, ''); + popUpCal._lastInput = input; + inst._setDateFromField(input); + if (popUpCal._inDialog) { // hide cursor + input.value = ''; + } + if (!popUpCal._pos) { // position below input + popUpCal._pos = popUpCal._findPos(input); + popUpCal._pos[1] += input.offsetHeight; + } + inst._calendarDiv.css('position', (popUpCal._inDialog && $.blockUI ? 'static' : 'absolute')). + css('left', popUpCal._pos[0] + 'px').css('top', popUpCal._pos[1] + 'px'); + popUpCal._pos = null; + var fieldSettings = inst._get('fieldSettings'); + $.extend(inst._settings, (fieldSettings ? fieldSettings(input) : {})); + popUpCal._showCalendar(inst); + }, + + /* Construct and display the calendar. */ + _showCalendar: function(id) { + var inst = this._getInst(id); + popUpCal._updateCalendar(inst); + if (!inst._inline) { + var speed = inst._get('speed'); + inst._calendarDiv.show(speed, function() { + popUpCal._popUpShowing = true; + popUpCal._afterShow(inst); + }); + if (speed == '') { + popUpCal._popUpShowing = true; + popUpCal._afterShow(inst); + } + if (inst._input[0].type != 'hidden') { + inst._input[0].focus(); + } + this._curInst = inst; + } + }, + + /* Generate the calendar content. */ + _updateCalendar: function(inst) { + inst._calendarDiv.empty().append(inst._generateCalendar()); + if (inst._input && inst._input != 'hidden') { + inst._input[0].focus(); + } + }, + + /* Tidy up after displaying the calendar. */ + _afterShow: function(inst) { + if ($.browser.msie) { // fix IE < 7 select problems + $('#calendar_cover').css({width: inst._calendarDiv[0].offsetWidth + 4, + height: inst._calendarDiv[0].offsetHeight + 4}); + } + /*// re-position on screen if necessary + var calDiv = inst._calendarDiv[0]; + var pos = popUpCal._findPos(inst._input[0]); + if ((calDiv.offsetLeft + calDiv.offsetWidth) > + (document.body.clientWidth + document.body.scrollLeft)) { + inst._calendarDiv.css('left', (pos[0] + inst._input[0].offsetWidth - calDiv.offsetWidth) + 'px'); + } + if ((calDiv.offsetTop + calDiv.offsetHeight) > + (document.body.clientHeight + document.body.scrollTop)) { + inst._calendarDiv.css('top', (pos[1] - calDiv.offsetHeight) + 'px'); + }*/ + }, + + /* Hide the calendar from view. + @param id string/object - the ID of the current calendar instance, + or the instance itself + @param speed string - the speed at which to close the calendar + @return void */ + hideCalendar: function(id, speed) { + var inst = this._getInst(id); + if (popUpCal._popUpShowing) { + speed = (speed != null ? speed : inst._get('speed')); + inst._calendarDiv.hide(speed, function() { + popUpCal._tidyDialog(inst); + }); + if (speed == '') { + popUpCal._tidyDialog(inst); + } + popUpCal._popUpShowing = false; + popUpCal._lastInput = null; + inst._settings.prompt = null; + if (popUpCal._inDialog) { + popUpCal._dialogInput.css('position', 'absolute'). + css('left', '0px').css('top', '-100px'); + if ($.blockUI) { + $.unblockUI(); + $('body').append(this._calendarDiv); + } + } + popUpCal._inDialog = false; + } + popUpCal._curInst = null; + }, + + /* Tidy up after a dialog display. */ + _tidyDialog: function(inst) { + inst._calendarDiv.removeClass('calendar_dialog'); + $('.calendar_prompt', inst._calendarDiv).remove(); + }, + + /* Close calendar if clicked elsewhere. */ + _checkExternalClick: function(event) { + if (!popUpCal._curInst) { + return; + } + var target = $(event.target); + if( (target.parents("#calendar_div").length == 0) + && (target.attr('class') != 'calendar_trigger') + && popUpCal._popUpShowing + && !(popUpCal._inDialog && $.blockUI) ) + { + popUpCal.hideCalendar(popUpCal._curInst, ''); + } + }, + + /* Adjust one of the date sub-fields. */ + _adjustDate: function(id, offset, period) { + var inst = this._getInst(id); + inst._adjustDate(offset, period); + this._updateCalendar(inst); + }, + + /* Action for current link. */ + _gotoToday: function(id) { + var date = new Date(); + var inst = this._getInst(id); + inst._selectedDay = date.getDate(); + inst._selectedMonth = date.getMonth(); + inst._selectedYear = date.getFullYear(); + this._adjustDate(inst); + }, + + /* Action for selecting a new month/year. */ + _selectMonthYear: function(id, select, period) { + var inst = this._getInst(id); + inst._selectingMonthYear = false; + inst[period == 'M' ? '_selectedMonth' : '_selectedYear'] = + select.options[select.selectedIndex].value - 0; + this._adjustDate(inst); + }, + + /* Restore input focus after not changing month/year. */ + _clickMonthYear: function(id) { + var inst = this._getInst(id); + if (inst._input && inst._selectingMonthYear && !$.browser.msie) { + inst._input[0].focus(); + } + inst._selectingMonthYear = !inst._selectingMonthYear; + }, + + /* Action for changing the first week day. */ + _changeFirstDay: function(id, a) { + var inst = this._getInst(id); + var dayNames = inst._get('dayNames'); + var value = a.firstChild.nodeValue; + for (var i = 0; i < 7; i++) { + if (dayNames[i] == value) { + inst._settings.firstDay = i; + break; + } + } + this._updateCalendar(inst); + }, + + /* Action for selecting a day. */ + _selectDay: function(id, td) { + var inst = this._getInst(id); + inst._selectedDay = $("a", td).html(); + this._selectDate(id); + }, + + /* Erase the input field and hide the calendar. */ + _clearDate: function(id) { + this._selectDate(id, ''); + }, + + /* Update the input field with the selected date. */ + _selectDate: function(id, dateStr) { + var inst = this._getInst(id); + dateStr = (dateStr != null ? dateStr : inst._formatDate()); + if (inst._input) { + inst._input.val(dateStr); + } + var onSelect = inst._get('onSelect'); + if (onSelect) { + onSelect(dateStr); // trigger custom callback + } + else { + inst._input.trigger('change'); // fire the change event + } + if (inst._inline) { + this._updateCalendar(inst); + } + else { + this.hideCalendar(inst, inst._get('speed')); + } + }, + + /* Set as customDate function to prevent selection of weekends. + @param date Date - the date to customise + @return [boolean, string] - is this date selectable?, what is its CSS class? */ + noWeekends: function(date) { + var day = date.getDay(); + return [(day > 0 && day < 6), '']; + }, + + /* Find an object's position on the screen. */ + _findPos: function(obj) { + if (obj.type == 'hidden') { + obj = obj.nextSibling; + } + var curleft = curtop = 0; + if (obj.offsetParent) { + curleft = obj.offsetLeft; + curtop = obj.offsetTop; + while (obj = obj.offsetParent) { + var origcurleft = curleft; + curleft += obj.offsetLeft; + if (curleft < 0) { + curleft = origcurleft; + } + curtop += obj.offsetTop; + } + } + return [curleft,curtop]; + } +}); + +/* Individualised settings for calendars applied to one or more related inputs. + Instances are managed and manipulated through the PopUpCal manager. */ +function PopUpCalInstance(settings, inline) { + this._id = popUpCal._register(this); + this._selectedDay = 0; + this._selectedMonth = 0; // 0-11 + this._selectedYear = 0; // 4-digit year + this._input = null; // The attached input field + this._inline = inline; // True if showing inline, false if used in a popup + this._calendarDiv = (!inline ? popUpCal._calendarDiv : + $('<div id="calendar_div_' + this._id + '" class="calendar_inline"></div>')); + if (inline) { + var date = new Date(); + this._currentDay = date.getDate(); + this._currentMonth = date.getMonth(); + this._currentYear = date.getFullYear(); + } + // customise the calendar object - uses manager defaults if not overridden + this._settings = $.extend({}, settings || {}); // clone +} + +$.extend(PopUpCalInstance.prototype, { + /* Get a setting value, defaulting if necessary. */ + _get: function(name) { + return (this._settings[name] != null ? this._settings[name] : popUpCal._defaults[name]); + }, + + /* Parse existing date and initialise calendar. */ + _setDateFromField: function(input) { + this._input = $(input); + var dateFormat = this._get('dateFormat'); + var currentDate = this._input.val().split(dateFormat.charAt(3)); + if (currentDate.length == 3) { + this._currentDay = parseInt(currentDate[dateFormat.indexOf('D')], 10); + this._currentMonth = parseInt(currentDate[dateFormat.indexOf('M')], 10) - 1; + this._currentYear = parseInt(currentDate[dateFormat.indexOf('Y')], 10); + } + else { + var date = new Date(); + this._currentDay = date.getDate(); + this._currentMonth = date.getMonth(); + this._currentYear = date.getFullYear(); + } + this._selectedDay = this._currentDay; + this._selectedMonth = this._currentMonth; + this._selectedYear = this._currentYear; + this._adjustDate(); + }, + + /* Set the date directly. */ + _setDate: function(date) { + this._selectedDay = this._currentDay = date.getDate(); + this._selectedMonth = this._currentMonth = date.getMonth(); + this._selectedYear = this._currentYear = date.getFullYear(); + this._adjustDate(); + }, + + /* Retrieve the date directly. */ + _getDate: function() { + return new Date(this._currentYear, this._currentMonth, this._currentDay); + }, + + /* Generate the HTML for the current state of the calendar. */ + _generateCalendar: function() { + var today = new Date(); + today = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // clear time + // build the calendar HTML + var controls = '<div class="calendar_control">' + + '<a class="calendar_clear" onclick="popUpCal._clearDate(' + this._id + ');">' + + this._get('clearText') + '</a>' + + '<a class="calendar_close" onclick="popUpCal.hideCalendar(' + this._id + ');">' + + this._get('closeText') + '</a></div>'; + var prompt = this._get('prompt'); + var closeAtTop = this._get('closeAtTop'); + var hideIfNoPrevNext = this._get('hideIfNoPrevNext'); + // controls and links + var html = (prompt ? '<div class="calendar_prompt">' + prompt + '</div>' : '') + + (closeAtTop && !this._inline ? controls : '') + '<div class="calendar_links">' + + (this._canAdjustMonth(-1) ? '<a class="calendar_prev" ' + + 'onclick="popUpCal._adjustDate(' + this._id + ', -1, \'M\');">' + this._get('prevText') + '</a>' : + (hideIfNoPrevNext ? '' : '<label class="calendar_prev">' + this._get('prevText') + '</label>')) + + (this._isInRange(today) ? '<a class="calendar_current" ' + + 'onclick="popUpCal._gotoToday(' + this._id + ');">' + this._get('currentText') + '</a>' : '') + + (this._canAdjustMonth(+1) ? '<a class="calendar_next" ' + + 'onclick="popUpCal._adjustDate(' + this._id + ', +1, \'M\');">' + this._get('nextText') + '</a>' : + (hideIfNoPrevNext ? '' : '<label class="calendar_next">' + this._get('nextText') + '</label>')) + + '</div><div class="calendar_header">'; + var minDate = this._get('minDate'); + var maxDate = this._get('maxDate'); + // month selection + var monthNames = this._get('monthNames'); + if (!this._get('changeMonth')) { + html += monthNames[this._selectedMonth] + ' '; + } + else { + var inMinYear = (minDate && minDate.getFullYear() == this._selectedYear); + var inMaxYear = (maxDate && maxDate.getFullYear() == this._selectedYear); + html += '<select class="calendar_newMonth" ' + + 'onchange="popUpCal._selectMonthYear(' + this._id + ', this, \'M\');" ' + + 'onclick="popUpCal._clickMonthYear(' + this._id + ');">'; + for (var month = 0; month < 12; month++) { + if ((!inMinYear || month >= minDate.getMonth()) && + (!inMaxYear || month <= maxDate.getMonth())) { + html += '<option value="' + month + '"' + + (month == this._selectedMonth ? ' selected="selected"' : '') + + '>' + monthNames[month] + '</option>'; + } + } + html += '</select>'; + } + // year selection + if (!this._get('changeYear')) { + html += this._selectedYear; + } + else { + // determine range of years to display + var years = this._get('yearRange').split(':'); + var year = 0; + var endYear = 0; + if (years.length != 2) { + year = this._selectedYear - 10; + endYear = this._selectedYear + 10; + } + else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') { + year = this._selectedYear + parseInt(years[0], 10); + endYear = this._selectedYear + parseInt(years[1], 10); + } + else { + year = parseInt(years[0], 10); + endYear = parseInt(years[1], 10); + } + year = (minDate ? Math.max(year, minDate.getFullYear()) : year); + endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); + html += '<select class="calendar_newYear" onchange="popUpCal._selectMonthYear(' + + this._id + ', this, \'Y\');" ' + 'onclick="popUpCal._clickMonthYear(' + + this._id + ');">'; + for (; year <= endYear; year++) { + html += '<option value="' + year + '"' + + (year == this._selectedYear ? ' selected="selected"' : '') + + '>' + year + '</option>'; + } + html += '</select>'; + } + html += '</div><table class="calendar" cellpadding="0" cellspacing="0"><thead>' + + '<tr class="calendar_titleRow">'; + var firstDay = this._get('firstDay'); + var changeFirstDay = this._get('changeFirstDay'); + var dayNames = this._get('dayNames'); + for (var dow = 0; dow < 7; dow++) { // days of the week + html += '<td>' + (!changeFirstDay ? '' : '<a onclick="popUpCal._changeFirstDay(' + + this._id + ', this);">') + dayNames[(dow + firstDay) % 7] + + (changeFirstDay ? '</a>' : '') + '</td>'; + } + html += '</tr></thead><tbody>'; + var daysInMonth = this._getDaysInMonth(this._selectedYear, this._selectedMonth); + this._selectedDay = Math.min(this._selectedDay, daysInMonth); + var leadDays = (this._getFirstDayOfMonth(this._selectedYear, this._selectedMonth) - firstDay + 7) % 7; + var currentDate = new Date(this._currentYear, this._currentMonth, this._currentDay); + var selectedDate = new Date(this._selectedYear, this._selectedMonth, this._selectedDay); + var printDate = new Date(this._selectedYear, this._selectedMonth, 1 - leadDays); + var numRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate + var customDate = this._get('customDate'); + var showOtherMonths = this._get('showOtherMonths'); + for (var row = 0; row < numRows; row++) { // create calendar rows + html += '<tr class="calendar_daysRow">'; + for (var dow = 0; dow < 7; dow++) { // create calendar days + var customSettings = (customDate ? customDate(printDate) : [true, '']); + var otherMonth = (printDate.getMonth() != this._selectedMonth); + var unselectable = otherMonth || !customSettings[0] || + (minDate && printDate < minDate) || (maxDate && printDate > maxDate); + html += '<td class="calendar_daysCell' + + ((dow + firstDay + 6) % 7 >= 5 ? ' calendar_weekEndCell' : '') + // highlight weekends + (otherMonth ? ' calendar_otherMonth' : '') + // highlight days from other months + (printDate.getTime() == selectedDate.getTime() ? ' calendar_daysCellOver' : '') + // highlight selected day + (unselectable ? ' calendar_unselectable' : '') + // highlight unselectable days + (!otherMonth || showOtherMonths ? ' ' + customSettings[1] : '') + // highlight custom dates + (printDate.getTime() == currentDate.getTime() ? ' calendar_currentDay' : // highlight current day + (printDate.getTime() == today.getTime() ? ' calendar_today' : '')) + '"' + // highlight today (if different) + (unselectable ? '' : ' onmouseover="$(this).addClass(\'calendar_daysCellOver\');"' + + ' onmouseout="$(this).removeClass(\'calendar_daysCellOver\');"' + + ' onclick="popUpCal._selectDay(' + this._id + ', this);"') + '>' + // actions + (otherMonth ? (showOtherMonths ? printDate.getDate() : ' ') : // display for other months + (unselectable ? printDate.getDate() : '<a>' + printDate.getDate() + '</a>')) + '</td>'; // display for this month + printDate.setDate(printDate.getDate() + 1); + } + html += '</tr>'; + } + html += '</tbody></table>' + (!closeAtTop && !this._inline ? controls : '') + + '<div style="clear: both;"></div>' + (!$.browser.msie ? '' : + '<!--[if lte IE 6.5]><iframe src="javascript:false;" class="calendar_cover"></iframe><![endif]-->'); + return html; + }, + + /* Adjust one of the date sub-fields. */ + _adjustDate: function(offset, period) { + var date = new Date(this._selectedYear + (period == 'Y' ? offset : 0), + this._selectedMonth + (period == 'M' ? offset : 0), + this._selectedDay + (period == 'D' ? offset : 0)); + // ensure it is within the bounds set + var minDate = this._get('minDate'); + var maxDate = this._get('maxDate'); + date = (minDate && date < minDate ? minDate : date); + date = (maxDate && date > maxDate ? maxDate : date); + this._selectedDay = date.getDate(); + this._selectedMonth = date.getMonth(); + this._selectedYear = date.getFullYear(); + }, + + /* Find the number of days in a given month. */ + _getDaysInMonth: function(year, month) { + return 32 - new Date(year, month, 32).getDate(); + }, + + /* Find the day of the week of the first of a month. */ + _getFirstDayOfMonth: function(year, month) { + return new Date(year, month, 1).getDay(); + }, + + /* Determines if we should allow a "next/prev" month display change. */ + _canAdjustMonth: function(offset) { + var date = new Date(this._selectedYear, this._selectedMonth + offset, 1); + if (offset < 0) { + date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); + } + return this._isInRange(date); + }, + + /* Is the given date in the accepted range? */ + _isInRange: function(date) { + var minDate = this._get('minDate'); + var maxDate = this._get('maxDate'); + return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate)); + }, + + /* Format the given date for display. */ + _formatDate: function() { + var day = this._currentDay = this._selectedDay; + var month = this._currentMonth = this._selectedMonth; + var year = this._currentYear = this._selectedYear; + month++; // adjust javascript month + var dateFormat = this._get('dateFormat'); + var dateString = ''; + for (var i = 0; i < 3; i++) { + dateString += dateFormat.charAt(3) + + (dateFormat.charAt(i) == 'D' ? (day < 10 ? '0' : '') + day : + (dateFormat.charAt(i) == 'M' ? (month < 10 ? '0' : '') + month : + (dateFormat.charAt(i) == 'Y' ? year : '?'))); + } + return dateString.substring(dateFormat.charAt(3) ? 1 : 0); + } +}); + +/* Attach the calendar to a jQuery selection. + @param settings object - the new settings to use for this calendar instance (anonymous) + @return jQuery object - for chaining further calls */ +$.fn.calendar = function(settings) { + return this.each(function() { + // check for settings on the control itself - in namespace 'cal:' + var inlineSettings = null; + for (attrName in popUpCal._defaults) { + var attrValue = this.getAttribute('cal:' + attrName); + if (attrValue) { + inlineSettings = inlineSettings || {}; + try { + inlineSettings[attrName] = eval(attrValue); + } + catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + var nodeName = this.nodeName.toLowerCase(); + if (nodeName == 'input') { + var instSettings = (inlineSettings ? $.extend($.extend({}, settings || {}), + inlineSettings || {}) : settings); // clone and customise + var inst = (inst && !inlineSettings ? inst : + new PopUpCalInstance(instSettings, false)); + popUpCal._connectCalendar(this, inst); + } + else if (nodeName == 'div' || nodeName == 'span') { + var instSettings = $.extend($.extend({}, settings || {}), + inlineSettings || {}); // clone and customise + var inst = new PopUpCalInstance(instSettings, true); + popUpCal._inlineCalendar(this, inst); + } + }); +}; + +/* Initialise the calendar. */ +$(document).ready(function() { + popUpCal = new PopUpCal(); // singleton instance +}); diff --git a/modules/API/Request.php b/modules/API/Request.php index 767f2269601294aa17ffde984bc8eff32d72c72c..17397949576ac4a058c94d0d45a3390eeaf3eed4 100644 --- a/modules/API/Request.php +++ b/modules/API/Request.php @@ -168,7 +168,7 @@ class Piwik_API_Request switch($format) { case 'xml': - header('Content-type: text/xml'); + @header('Content-type: text/xml'); $return = '<?xml version="1.0" encoding="utf-8" ?>'. '<result>'. @@ -176,7 +176,7 @@ class Piwik_API_Request '</result>'; break; case 'json': - header( "Content-type: application/json" ); + @header( "Content-type: application/json" ); $return = '{"result":"success", "message":"ok"}'; break; case 'php': diff --git a/modules/ArchiveProcessing.php b/modules/ArchiveProcessing.php index 386421c454d581bee46fae9f527e9086c2b1b042..1cddc83eb84b9a5dca4dfcf000cc2e8f20ced42e 100644 --- a/modules/ArchiveProcessing.php +++ b/modules/ArchiveProcessing.php @@ -122,11 +122,11 @@ abstract class Piwik_ArchiveProcessing $this->postCompute(); Piwik::printMemoryUsage('After post compute'); - Piwik::log("New archive computed, id = {$this->idArchive}"); +// Piwik::log("New archive computed, id = {$this->idArchive}"); } else { - Piwik::log("Archive already available, id = {$this->idArchive}"); + //Piwik::log("Archive already available, id = {$this->idArchive}"); } return $this->idArchive; diff --git a/modules/ArchiveProcessing/Day.php b/modules/ArchiveProcessing/Day.php index 14bdf8b2a40af0638b01eb7077a1501e70962355..78063b2490727ab8a8541b2eb9ef211e393a59ba 100644 --- a/modules/ArchiveProcessing/Day.php +++ b/modules/ArchiveProcessing/Day.php @@ -53,7 +53,6 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing { $record = new Piwik_ArchiveProcessing_Record_Numeric($name, $value); } - Piwik::log($row); Piwik_PostEvent('ArchiveProcessing_Day.compute', $this); } diff --git a/modules/Common.php b/modules/Common.php index ed12510905dc67af4e7fd9731354bb6acfe000b5..bc91fabc29916a898c17cf33e4cb438cd71f6765 100644 --- a/modules/Common.php +++ b/modules/Common.php @@ -506,25 +506,51 @@ class Piwik_Common */ static public function getParameterFromQueryString( $urlQuery, $parameter) { - $refererQuery = '&'.trim(str_replace(array('%20'), ' ', '&'.$urlQuery)); - $word = '&'.$parameter.'='; - - if( $off = strrpos($refererQuery, $word)) + $nameToValue = self::getArrayFromQueryString($urlQuery); + + if(isset($nameToValue[$parameter])) { - $off += strlen($word); // &q= - $str = substr($refererQuery, $off); - $len = strpos($str, '&'); - if($len === false) - { - $len = strlen($str); - } - $toReturn = substr($refererQuery, $off, $len); - return $toReturn; + return $nameToValue[$parameter]; } - else + return false; + } + + /** + * Returns an URL query string in an array format + * + * @param string urlQuery + * @return array array( param1=> value1, param2=>value2) + */ + static public function getArrayFromQueryString( $urlQuery ) + { + if(strlen($urlQuery) == 0) { - return false; + return array(); + } + if($urlQuery[0] == '?') + { + $urlQuery = substr($urlQuery, 1); + } + + $separator = '&'; + + $urlQuery = $separator . $urlQuery; +// $urlQuery = str_replace(array('%20'), ' ', $urlQuery); + $refererQuery = trim($urlQuery); + + $values = explode($separator, $refererQuery); + + $nameToValue = array(); + + foreach($values as $value) + { + if( false !== strpos($value, '=')) + { + $exploded = explode('=',$value); + $nameToValue[$exploded[0]] = $exploded[1]; + } } + return $nameToValue; } } diff --git a/modules/DataTable/Manager.php b/modules/DataTable/Manager.php index a7647d652d203e49031a2752b3d90c59e7f73972..9d5cf4ba53fd6bf24a937ec413836ff3fb144a86 100644 --- a/modules/DataTable/Manager.php +++ b/modules/DataTable/Manager.php @@ -60,7 +60,6 @@ class Piwik_DataTable_Manager */ public function deleteAll() { - Piwik::log("DELETE ALL ".$this->count()." TABLES"); $this->tables = array(); } diff --git a/modules/DataTable/Renderer/XML.php b/modules/DataTable/Renderer/XML.php index 90f03f46af0449bf19bcf91961a311dd42a0613d..2c82b251a5e9b50a5ce1bc287182c11708ace65f 100644 --- a/modules/DataTable/Renderer/XML.php +++ b/modules/DataTable/Renderer/XML.php @@ -51,6 +51,7 @@ class Piwik_DataTable_Renderer_XML extends Piwik_DataTable_Renderer $xmlStr = str_replace(">\n", ">\n\t",$xmlStr); $xmlStr = str_replace("\t</result>", "</result>",$xmlStr); } + header('Content-type: text/xml'); return $xmlStr; } } \ No newline at end of file diff --git a/modules/Date.php b/modules/Date.php index 424d0357e1c18846fe9c1d13c44134227f044783..d4a21742f2c030411c79d8d1b5ee46a7f7cb3a8f 100644 --- a/modules/Date.php +++ b/modules/Date.php @@ -24,14 +24,17 @@ class Piwik_Date { return $this->timestamp; } + public function isEarlier(Piwik_Date $date) { return $this->getTimestamp() < $date->getTimestamp(); } + public function toString($part = 'Y-m-d') { return date($part, $this->getTimestamp()); } + /** * Sets a new day * Returned is the new date object diff --git a/modules/ErrorHandler.php b/modules/ErrorHandler.php index e541cb2a28f1ff5f93e68fb373d9c4fc3cdf1f20..5887e071ff5cf49547863b0ccbcf8d6b021f5773 100755 --- a/modules/ErrorHandler.php +++ b/modules/ErrorHandler.php @@ -5,10 +5,10 @@ */ function Piwik_ErrorHandler($errno, $errstr, $errfile, $errline) { -// ob_start(); -// debug_print_backtrace(); -// $backtrace = ob_get_contents(); -// ob_end_clean(); + ob_start(); + debug_print_backtrace(); + $backtrace = ob_get_contents(); + ob_end_clean(); Zend_Registry::get('logger_error')->log($errno, $errstr, $errfile, $errline, $backtrace); switch($errno) diff --git a/modules/FrontController.php b/modules/FrontController.php index 32f92b5e0715ac164a05fad286c387d021af8fb8..bf94afb38409cb2cfd55dc63e9ad8aa5649ca545 100644 --- a/modules/FrontController.php +++ b/modules/FrontController.php @@ -69,19 +69,16 @@ class Piwik_FrontController function end() { - - Piwik::printZendProfiler(); - Piwik::printMemoryUsage(); - Piwik::printQueryCount(); +// Piwik::printZendProfiler(); +// Piwik::printMemoryUsage(); +// Piwik::printQueryCount(); // Piwik::uninstall(); - - Piwik::log($this->timer); - +// } function init() { - $this->timer = new Piwik_Timer; + Zend_Registry::set('timer', new Piwik_Timer); //move into a init() method Piwik::createConfigObject(); @@ -107,6 +104,10 @@ class Piwik_FrontController Piwik::prefixTable('log_action'), Piwik::prefixTable('log_profiling'), Piwik::prefixTable('archive'), + Piwik::prefixTable('logger_api_call'), + Piwik::prefixTable('logger_error'), + Piwik::prefixTable('logger_exception'), + Piwik::prefixTable('logger_message'), ); Piwik::dropTables($doNotDrop); diff --git a/modules/Piwik.php b/modules/Piwik.php index 6d10c4daf342b64b78002ac14dd8323ffa7ebb00..d0e93960ed2064f2401fd6669438fee5b7655955 100755 --- a/modules/Piwik.php +++ b/modules/Piwik.php @@ -573,7 +573,7 @@ class Piwik //create tables $db = Zend_Registry::get('db'); - Piwik::log("Droping ". implode(", ", self::getTablesNames())); +// Piwik::log("Droping ". implode(", ", self::getTablesNames())); $db->query( "DROP TABLE IF EXISTS ". implode(", ", self::getTablesNames()) ); } diff --git a/modules/SmartyPlugins/function.url.php b/modules/SmartyPlugins/function.url.php new file mode 100644 index 0000000000000000000000000000000000000000..0fbb5726ab1e73d61aa3c81ed654672f07f4a943 --- /dev/null +++ b/modules/SmartyPlugins/function.url.php @@ -0,0 +1,46 @@ +<?php +/** + * Smarty plugin + * @package Smarty + * @subpackage plugins + */ + + +/** + * Smarty {mailto} function plugin + * + * Examples: + * <pre> + * {mailto address="me@domain.com"} + * {mailto address="me@domain.com" encode="javascript"} + * {mailto address="me@domain.com" encode="hex"} + * {mailto address="me@domain.com" subject="Hello to you!"} + * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"} + * {mailto address="me@domain.com" extra='class="mailto"'} + * </pre> + * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto} + * (Smarty online manual) + * @version 1.2 + * @author Monte Ohrt <monte at ohrt dot com> + * @author credits to Jason Sweat (added cc, bcc and subject functionality) + * @param array + * @param Smarty + * @return string + */ +function smarty_function_url($params, &$smarty) +{ + $queryString = Piwik_Url::getCurrentQueryString(); + $queryString = htmlspecialchars($queryString); + $urlValues = Piwik_Common::getArrayFromQueryString($queryString); +// var_dump($urlValues); + foreach($params as $key => $value) + { + $urlValues[$key] = $value; + } + + return '?' . http_build_query($urlValues); +} + +/* vim: set expandtab: */ + +?> diff --git a/modules/View.php b/modules/View.php index 3ae6b96baac7d86571c4c960536dca9e16d7fc59..2641c95a703cf67ebc90826a01416e9ff9ad50bd 100644 --- a/modules/View.php +++ b/modules/View.php @@ -52,6 +52,7 @@ class Piwik_View public function render() { + $this->totalTimeGeneration = Zend_Registry::get('timer')->getTime(); // $this->smarty->assign('smarty', $this); return $this->smarty->fetch($this->template); } diff --git a/plugins/Actions.php b/plugins/Actions.php index 48c55d7d9d63ffbaae2c8e233bddda26abaa4e0a..526410d88a92dfc1123ae86ab83b1416eff38f73 100644 --- a/plugins/Actions.php +++ b/plugins/Actions.php @@ -81,7 +81,6 @@ class Piwik_Actions extends Piwik_Plugin $timer = new Piwik_Timer; - Piwik::printMemoryUsage(); //TODO map nb_visits etc. with numeric indexes to save space, memor and time /* @@ -101,9 +100,6 @@ class Piwik_Actions extends Piwik_Plugin $modified = $this->updateActionsTableWithRowQuery($query); - Piwik::log("$modified rows for all actions"); - - Piwik::printMemoryUsage(); /* * Entry actions @@ -126,9 +122,6 @@ class Piwik_Actions extends Piwik_Plugin $modified = $this->updateActionsTableWithRowQuery($query); - Piwik::log("$modified rows for entry actions"); - -// Piwik::printMemoryUsage(); /* * Exit actions @@ -149,9 +142,6 @@ class Piwik_Actions extends Piwik_Plugin $modified = $this->updateActionsTableWithRowQuery($query); - Piwik::log("$modified rows for exit actions"); - -// Piwik::printMemoryUsage(); /* * Time per action */ @@ -169,29 +159,22 @@ class Piwik_Actions extends Piwik_Plugin $modified = $this->updateActionsTableWithRowQuery($query); - Piwik::log("$modified rows for sum time per action"); - - Piwik::printMemoryUsage("Middle of ".get_class($this)." "); $dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_LogStats_Action::TYPE_ACTION]); $s = $dataTable->getSerialized(); $record = new Piwik_ArchiveProcessing_Record_Blob_Array('Actions_actions', $s); - Piwik::log(" Action serialized has ".count($s)." elements"); $dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_LogStats_Action::TYPE_DOWNLOAD]); $s = $dataTable->getSerialized(); $record = new Piwik_ArchiveProcessing_Record_Blob_Array('Actions_downloads', $s); - Piwik::log(" Download serialized has ".count($s)." elements"); $dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_LogStats_Action::TYPE_OUTLINK]); $s = $dataTable->getSerialized(); $record = new Piwik_ArchiveProcessing_Record_Blob_Array('Actions_outlink', $s); - Piwik::log(" Outlink serialized has ".count($s)." elements"); unset($this->actionsTablesByType); - Piwik::printMemoryUsage("End of ".get_class($this)." "); } static public function getActionCategoryFromName($name) diff --git a/plugins/Referers/API.php b/plugins/Referers/API.php index ba0116b6504e6118917ad7905e5499dd4596d130..bde0c697f55252b686587972e7c26fc13c6264b6 100644 --- a/plugins/Referers/API.php +++ b/plugins/Referers/API.php @@ -88,6 +88,7 @@ class Piwik_Referers_API extends Piwik_Apiable $dataTable = $this->getDataTable('Referers_urlByWebsite',$idSite, $period, $date, $idSubtable); $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackAddDetail', array( 'label', 'url', create_function('$label', 'return $label;')) ); $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_getPathFromUrl')); + $dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_truncatePath')); return $dataTable; } @@ -153,6 +154,17 @@ function Piwik_getPathFromUrl($url) return $path; } +function Piwik_truncatePath( $path ) +{ + $limit = 27; + $path = htmlspecialchars_decode($path); + $len = strlen($path); + if($len > $limit) + { + $path = substr($path, 0, $limit-3) . "..."; + } + return htmlspecialchars($path); +} function Piwik_getSearchEngineUrlFromName($name) { diff --git a/plugins/UserSettings/Controller.php b/plugins/UserSettings/Controller.php index 2ac7cfca651acfe49b401a8ac5d4c7ad968d6112..0838bbff458030ba9772f4fff3964aec00f1c5e2 100644 --- a/plugins/UserSettings/Controller.php +++ b/plugins/UserSettings/Controller.php @@ -13,6 +13,10 @@ class Piwik_UserSettings_Controller extends Piwik_Controller $view->period = Piwik_Common::getRequestVar('period'); $view->idSite = Piwik_Common::getRequestVar('idSite'); + $view->userLogin = Piwik::getCurrentUserLogin(); + $view->sites = Piwik_SitesManager_API::getSitesWithAtLeastViewAccess(); + $view->url = Piwik_Url::getCurrentUrl(); + $view->dataTableActions = $this->getActions( true ); $view->dataTableDownloads = $this->getDownloads( true ); $view->dataTableOutlinks = $this->getOutlinks( true ); @@ -75,7 +79,6 @@ class Piwik_UserSettings_Controller extends Piwik_Controller $view->numberDistinctPartners = $this->getNumberOfDistinctPartners(true); $view->numberDistinctPartnersUrls = $this->getNumberOfDistinctPartnersUrls(true); - echo $view->render(); } diff --git a/plugins/UserSettings/templates/index.tpl b/plugins/UserSettings/templates/index.tpl index dd74bf02b1a93d515601bf9d27f41aa5bb35c652..9993993ca318295e809418afb3bc46230e20c14a 100644 --- a/plugins/UserSettings/templates/index.tpl +++ b/plugins/UserSettings/templates/index.tpl @@ -8,6 +8,12 @@ <link rel="stylesheet" href="libs/jquery/tooltip/jquery.tooltip.css"> <link rel="stylesheet" href="plugins/UserSettings/templates/datatable.css"> + +<script> +var period = "{$period}"; +var currentDateStr = "{$date}"; +</script> + {literal} <style> tr.level0 td.label{ @@ -29,15 +35,151 @@ tr td.label img.plusMinus { margin-left:-1em; position:absolute; } + + + + + +.calendar td.testSelect, .calendar td.testSelect a{ + color:red; + border-color:red; +} </style> + + +<style type="text/css">@import url(libs/jquery/jquery-calendar.css);</style> +<script type="text/javascript" src="libs/jquery/jquery-calendar.js"></script> +<script> + +Date.prototype.getWeek = function (dowOffset) { + /*getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.meanfreepath.com */ + + dowOffset = typeof(dowOffset) == 'int' ? dowOffset : 0; //default dowOffset to zero + var newYear = new Date(this.getFullYear(),0,1); + var day = newYear.getDay() - dowOffset; //the day of week the year begins on + day = (day >= 0 ? day : day + 7); + var daynum = Math.floor((this.getTime() - newYear.getTime() - + (this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1; + var weeknum; + //if the year starts before the middle of a week + if(day < 4) { + weeknum = Math.floor((daynum+day-1)/7) + 1; + if(weeknum > 52) { + nYear = new Date(this.getFullYear() + 1,0,1); + nday = nYear.getDay() - dowOffset; + nday = nday >= 0 ? nday : nday + 7; + /*if the next year starts before the middle of + the week, it is week #1 of that year*/ + weeknum = nday < 4 ? 1 : 53; + } + } + else { + weeknum = Math.floor((daynum+day-1)/7); + } + return weeknum; +}; + +var splitDate = currentDateStr.split("-"); +var currentYear = splitDate[0]; +var currentMonth = splitDate[1]; +var currentDay = splitDate[2]; + +var currentDate = new Date(currentYear, currentMonth, currentDay); + + + +function isDateSelected( date ) +{ + var valid = false; + if(period == "month" || period == "year") + { + valid = true; + } + else if(period == "week" && date.getWeek(1) == currentDate.getWeek(1) ) + { + valid = true; + } + else if( period == "day" && date.getDate() == currentDate.getDate() ) + { + valid = true; + } + + if(valid) + { + return [true, 'testSelect']; + } + return [true, '']; +} + + +function updateDate() +{ + var date = formatDate(popUpCal.getDateFor($('#chooseDate')[0])); + + var currentUrl = window.location.href; + if((startStrDate = currentUrl.indexOf("date")) >= 0) + { + var dateToReplace = currentUrl.substring( + startStrDate + 4+1, + startStrDate +4+1 +4+1+2+1+2 + ); + regDateToReplace = new RegExp(dateToReplace, 'ig'); + currentUrl = currentUrl.replace( regDateToReplace, date ); + } + else + { + currentUrl = currentUrl + '&date=' + date; + } + + window.location.href = currentUrl; +} + +function formatDate(date) +{ + var day = date.getDate(); + var month = date.getMonth() + 1; + return date.getFullYear() + '-' + + (month < 10 ? '0' : '') + month + '-' + + (day < 10 ? '0' : '') + day ; +} + +$(document).ready(function(){ + $("#chooseDate").calendar({ + onSelect: updateDate, + dateFormat: 'DMY-', + firstDay: 1, + minDate: new Date(2007, 1 - 1, 1), + maxDate: new Date(2007, 12 - 1, 31), + changeFirstDay: false, + prevText: "", + nextText: "", + currentText: "", + customDate: isDateSelected + }); + } +); +</script> + + {/literal} + + +<div class="calendarInline" id="inlineFrom"></div> + +<br> + <h1>Piwik reports</h1> +<span id="chooseDate"></span> <p>- Date = {$date}</p> -<p>- Period = {$period}</p> -<p>- IdSite = {$idSite}</p> +<p>Url = {url}</p> +<p>User logged = {$userLogin}</p> +{include file="UserSettings/templates/period_select.tpl"} +{include file="UserSettings/templates/sites_select.tpl"} + <h2>Actions</h2> {$dataTableActions} +{* <h2>Downloads</h2> {$dataTableDownloads} <h2>Outlinks</h2> @@ -131,5 +273,6 @@ tr td.label img.plusMinus { {$dataTableNumberOfVisitsPerVisitDuration} <h3>Visits per number of pages</h3> {$dataTableNumberOfVisitsPerPage} +*} - \ No newline at end of file +{$totalTimeGeneration} seconds to generate the page \ No newline at end of file diff --git a/plugins/UserSettings/templates/period_select.tpl b/plugins/UserSettings/templates/period_select.tpl new file mode 100644 index 0000000000000000000000000000000000000000..723cbecfe182d9379e343f366a753d23b73e7c14 --- /dev/null +++ b/plugins/UserSettings/templates/period_select.tpl @@ -0,0 +1,5 @@ + +<a href="{url period=day}">Day</a> | +<a href="{url period=week}">Week</a> | +<a href="{url period=month}">Month</a> | +<a href="{url period=year}">Year</a> \ No newline at end of file diff --git a/plugins/UserSettings/templates/sites_select.tpl b/plugins/UserSettings/templates/sites_select.tpl new file mode 100644 index 0000000000000000000000000000000000000000..cc2e107203ef5e714a40db5f38e7e013efb55928 --- /dev/null +++ b/plugins/UserSettings/templates/sites_select.tpl @@ -0,0 +1,18 @@ +<!-- sites selection id="sites" --> +<div id="sites"> +Sites: +<form action="{$url}" method="post"> +{*<fieldset> + <legend> Sites </legend>*} + <p> + <select name="idSite" onchange="javascript:this.form.submit()"> + <optgroup label="Sites"> + {foreach from=$sites item=info} + <option label="{$info.name}" value="{$info.idsite}" {if $idSite==$info.idsite} selected="selected"{/if}>{$info.name}</option> + {/foreach} + </optgroup> + </select> + </p> +{*</fieldset>*} +</form> +</div> \ No newline at end of file