Invision Power Services, Inc. * @copyright (c) Invision Power Services, Inc. * @license https://www.invisioncommunity.com/legal/standards/ * @package Invision Community * @since 1 Jul 2015 */ namespace IPS\core\Statistics; /* To prevent PHP errors (extending class does not exist) revealing path */ if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) ) { header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' ); exit; } /** * Statistics Charts */ abstract class _Chart { /** * @brief Controller */ public $controller = NULL; /** * Get Chart * * @param \IPS\Http\Url $url URL the chart is being shown on. * * @return \IPS\Helpers\Chart */ abstract public function getChart( \IPS\Http\Url $url ): \IPS\Helpers\Chart; /** * Load from Extension * * @return static * @throws \OutOfRangeException */ public static function loadFromExtension( string $app, string $extension ): static { $extensions = \IPS\Application::load( $app )->extensions( 'core', 'Statistics' ); if ( isset( $extensions[ $extension ] ) ) { return $extensions[ $extension ]; } throw new \OutOfRangeException; } /** * Load from Controller * * @return static * @throws \OutOfRangeException */ public static function loadFromController( string $controller ): static { foreach( \IPS\Application::allExtensions( 'core', 'Statistics', FALSE ) AS $extension ) { if ( $extension->controller AND $extension->controller === $controller ) { return $extension; } } throw new \OutOfRangeException; } /** * Construct a saved chart from data * * @param array|int $data Chart ID or pre-loaded chart data. * @param \IPS\Http\Url $url URL chart is shown on * @param \IPS\Member|bool $check Check chart is owned by a specific member, or the currently logged in member if TRUE. If FALSE, no permission checking. * * @return \IPS\Helpers\Chart * @throws \OutOfRangeException * @throws \InvalidArgumentException */ public static function constructMemberChartFromData( array|int $data, \IPS\Http\Url $url, \IPS\Member|bool $check = TRUE ): \IPS\Helpers\Chart { try { if ( $check === FALSE ) { if ( !\is_array( $data ) ) { $data = \IPS\Db::i()->select( '*', 'core_saved_charts', array( "id=?", $data ) )->first(); } } else if ( ( $check instanceof \IPS\Member ) AND $check->member_id ) { if ( !\is_array( $data ) ) { $data = \IPS\Db::i()->select( '*', 'core_saved_charts', array( "chart_id=? AND chart_member=?", $data, $check->member_id ) )->first(); } else if ( $data['chart_member'] !== $check->member_id ) { throw new \UnderflowException; } } else if ( $check === TRUE AND \IPS\Member::loggedIn()->member_id ) { if ( !\is_array( $data ) ) { $data = \IPS\Db::i()->select( '*','core_saved_charts', array( "chart_id=? AND chart_member=?", $data, \IPS\Member::loggedIn()->member_id ) )->first(); } else if ( $data['chart_member'] !== \IPS\Member::loggedIn()->member_id ) { throw new \UnderflowException; } } else { /* If we're here, we were passed a guest object which isn't going to work. Throw a different exception as this should lead directly to a bugfix since this should never happen. */ throw new \InvalidArgumentException; } $extension = static::loadFromController( $data['chart_controller'] ); $chart = $extension->getChart( $url ); $currentFilters = array(); foreach( json_decode( $data['chart_configuration'], true ) AS $k => $v ) { if ( mb_substr( $k, 0, 11 ) == 'customform_' ) { $currentFilters[ mb_substr( $k, 11 ) ] = $v; } else { $currentFilters[ $k ] = $v; } } $chart->savedCustomFilters = $currentFilters; $chart->timescale = $data['chart_timescale'] ?? $chart->timescale; $chart->title = $data['chart_title']; $chart->showFilterTabs = FALSE; $chart->showIntervals = FALSE; $chart->showDateRange = FALSE; return $chart; } catch( \UnderflowException $e ) { /* Chart doesn't exist, or isn't owned by $member */ throw new \OutOfRangeException; } } /** * Get charts for Member * * @param \IPS\Http\Url $url URL * @param bool $idsOnly Return only ID's belonging to the user for lazyloading. * @param \IPS\Member|null $member Member, or NULL for currently logged in member. * * @return array * @throws \InvalidArgumentException */ public static function getChartsForMember( \IPS\Http\Url $url, bool $idsOnly = FALSE, ?\IPS\Member $member = NULL ): array { $member ??= \IPS\Member::loggedIn(); if ( !$member->member_id ) { throw new \InvalidArgumentException; } $return = []; foreach( \IPS\Db::i()->select( '*', 'core_saved_charts', array( "chart_member=?", $member->member_id ) ) AS $chart ) { if ( $idsOnly ) { $return[] = $chart['chart_id']; } else { try { $controller = explode( '_', $chart['chart_controller'] ); $return[$chart['chart_id']] = array( 'chart' => static::constructMemberChartFromData( $chart, $url, $member ), 'data' => $chart ); } catch( \OutOfRangeException ) { continue; } } } return $return; } }