<commit_before><?php
/**
 * 
 * Allows qualified (Admin) users a view into the state of the object cache.
 * Very useful for diagnosing problems when suspecting object(s) haven't been cached,
 * or you're experiencing other cache-related problems.
 * 
 * At time of writing, only detailed information on the "file" baxckend is available.
 * With any other backend, all you'll see is the Cache / DB comparison.
 * 
 * @author Deviate Ltd 2015 http://www.deviate.net.nz
 * @package silverstripe-cachable
 * @todo Add status for non-file backends
 */
class CacheableCacheInspectorController extends Controller {
    
    /**
     * 
     * @var array
     */
    private static $allowed_actions = array(
        'cacheable/cacheinspector'
    );
    
    /**
     * 
     * @var DataList
     */
    protected $_dbObjects = array();
    
    /**
     * 
     * @return void
     */
    public function init() {
        parent::init();
        
        if(!Permission::check('ADMIN')) {
            return $this->redirect('/', 403);
        }
    }
    
    /**
     * 
     * @param SS_HTTPRequest $request
     * @param string $action
     * @return HTMLText
     */
    public function handleAction($request, $action) {
        parent::handleAction($request, $action);
        
        return $this->inspect();
    }
    
    /**
     * 
     * Generate key information about the object cache.
     * 
     * @return HTMLText
     */
    public function inspect() {
        $backend = ucfirst(CacheableConfig::current_cache_mode());
        
        switch($backend) {            
            // File backend
            case 'File':
                $fileList = ArrayList::create($this->getCacheFiles());
                $backendData['FileTotal'] = $fileList->count();
                $backendData['FileList'] = $fileList;
                $backendData['FileCacheDir'] = CACHEABLE_STORE_DIR;
                $backendData['FileSizeOnDisk'] = (round($this->getCacheSize() / 1024, 2)) . 'Kb';
                $backendData['CacheLastEdited'] = $this->getCacheLastUpdated();
            break;
            // Memcached backend
            // TODO
            case 'memcached':
            // Memcache backend
            // TODO
            case 'memcache':
            // APCu backend
            // TODO
            case 'apc':
                break;
        }
        
        $comparisonData = array('StatusList' => ArrayList::create(array(
            $this->cacheToORMCompareDataObject('Stage', 'SiteTree'),
            $this->cacheToORMCompareDataObject('Live', 'SiteTree')
        )));
        $templateLocal = 'BackendData_' . $backend;
        $templateAbsolute = __DIR__ . '/../../templates/includes/' . $templateLocal . '.ss';
        
        $bData = '';
        if(file_exists($templateAbsolute)) {
            $bData = $this->renderWith($templateLocal, $backendData);
        }
        
        $backendData = array_merge(
            array('BackEndMode' => $backend),
            array('BackEndDataList' => $bData)
        );
        $viewable = array_merge(
            $comparisonData,
            $backendData
        );
        
        return $this->renderWith('Inspector', $viewable);
    }
    
    /**
     * 
     * Get the total no. objects in the cache. Due to the way {@link CacheableNavigation} 
     * works, this is restricted to "SiteTree-ish" objects only at this point.
     * 
     * @param string $stage
     * @param string $className
     * @return int $total
     */
    private function getTotalCachedObjects($stage, $className = 'CacheableSiteTree') {
        $conf = SiteConfig::current_site_config();
        $service = new CacheableNavigationService($stage, $conf);
        $cache = $service->getObjectCache();
        if($cache && $siteMap = $cache->get_site_map()) {
            $cachedSiteTree = ArrayList::create($siteMap);
            return $cachedSiteTree->count();
        }
        
        return 0;
    }
    
    /**
     * 
     * Get the total no. objects in the DB. Due to the way {@link CacheableNavigation} 
     * works, this is restricted to "SiteTree-ish" objects only at this point.
     * 
     * @param string $stage
     * @param string $className
     * @return int
     */
    private function getTotalDBObjects($stage, $className = 'SiteTree') {
        $mode = 'Stage.' . $stage;
        Versioned::set_reading_mode($mode);
        if(!$this->_dbObjects || !isset($this->_dbObjects[$stage])) {
            if($list = DataObject::get($className)) {<commit_msg>FIX: Fixes #47 Off by one error. - Restricts object count to those objects with non-null properties.<commit_after><?php
/**
 * 
 * Allows qualified (Admin) users a view into the state of the object cache.
 * Very useful for diagnosing problems when suspecting object(s) haven't been cached,
 * or you're experiencing other cache-related problems.
 * 
 * At time of writing, only detailed information on the "file" baxckend is available.
 * With any other backend, all you'll see is the Cache / DB comparison.
 * 
 * @author Deviate Ltd 2015 http://www.deviate.net.nz
 * @package silverstripe-cachable
 * @todo Add status for non-file backends
 */
class CacheableCacheInspectorController extends Controller {
    
    /**
     * 
     * @var array
     */
    private static $allowed_actions = array(
        'cacheable/cacheinspector'
    );
    
    /**
     * 
     * @var DataList
     */
    protected $_dbObjects = array();
    
    /**
     * 
     * @return void
     */
    public function init() {
        parent::init();
        
        if(!Permission::check('ADMIN')) {
            return $this->redirect('/', 403);
        }
    }
    
    /**
     * 
     * @param SS_HTTPRequest $request
     * @param string $action
     * @return HTMLText
     */
    public function handleAction($request, $action) {
        parent::handleAction($request, $action);
        
        return $this->inspect();
    }
    
    /**
     * 
     * Generate key information about the object cache.
     * 
     * @return HTMLText
     */
    public function inspect() {
        $backend = ucfirst(CacheableConfig::current_cache_mode());
        
        switch($backend) {            
            // File backend
            case 'File':
                $fileList = ArrayList::create($this->getCacheFiles());
                $backendData['FileTotal'] = $fileList->count();
                $backendData['FileList'] = $fileList;
                $backendData['FileCacheDir'] = CACHEABLE_STORE_DIR;
                $backendData['FileSizeOnDisk'] = (round($this->getCacheSize() / 1024, 2)) . 'Kb';
                $backendData['CacheLastEdited'] = $this->getCacheLastUpdated();
            break;
            // Memcached backend
            // TODO
            case 'memcached':
            // Memcache backend
            // TODO
            case 'memcache':
            // APCu backend
            // TODO
            case 'apc':
                break;
        }
        
        $comparisonData = array('StatusList' => ArrayList::create(array(
            $this->cacheToORMCompareDataObject('Stage', 'SiteTree'),
            $this->cacheToORMCompareDataObject('Live', 'SiteTree')
        )));
        $templateLocal = 'BackendData_' . $backend;
        $templateAbsolute = __DIR__ . '/../../templates/includes/' . $templateLocal . '.ss';
        
        $bData = '';
        if(file_exists($templateAbsolute)) {
            $bData = $this->renderWith($templateLocal, $backendData);
        }
        
        $backendData = array_merge(
            array('BackEndMode' => $backend),
            array('BackEndDataList' => $bData)
        );
        $viewable = array_merge(
            $comparisonData,
            $backendData
        );
        
        return $this->renderWith('Inspector', $viewable);
    }
    
    /**
     * 
     * Get the total no. objects in the cache. Due to the way {@link CacheableNavigation} 
     * works, this is restricted to "SiteTree-ish" objects only at this point.
     * 
     * @param string $stage
     * @param string $className
     * @return int $total
     */
    private function getTotalCachedObjects($stage, $className = 'CacheableSiteTree') {
        $conf = SiteConfig::current_site_config();
        $service = new CacheableNavigationService($stage, $conf);
        $cache = $service->getObjectCache();
        if($cache && $siteMap = $cache->get_site_map()) {
            // For reasons unknown, items appear in object-cache with NULL properties
            $cachedSiteTree = ArrayList::create($siteMap)->filterByCallback(function($item) {
                return !is_null($item->ParentID);
            });
            
            return $cachedSiteTree->count();
        }
        
        return 0;
    }
    
    /**
     * 
     * Get the total no. objects in the DB. Due to the way {@link CacheableNavigation} 
     * works, this is restricted to "SiteTree-ish" objects only at this point.
     * 
     * @param string $stage
     * @param string $className
     * @return int
     */
    private function getTotalDBObjects($stage, $className = 'SiteTree') {
        $mode = 'Stage.' . $stage;
        Versioned::set_reading_mode($mode);
        if(!$this->_dbObjects || !isset($this->_dbObjects[$stage])) {
            if($list = DataObject::get($className)) {
{'fraction_non_alphanumeric': 0.1259505194387919, 'fraction_numerical': 0.0029988218913998073, 'mean_word_length': 1.9550632911392405, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3430947', 'n_tokens_mistral': 2588, 'n_tokens_neox': 2497, 'n_words': 621}