public function get_addable_blocks() {
        $this->check_is_loaded();

        if (!is_null($this->addableblocks)) {
            return $this->addableblocks;
        }

        // Lazy load.
        $this->addableblocks = array();

        $allblocks = blocks_get_record();
        if (empty($allblocks)) {
            return $this->addableblocks;
        }

        $unaddableblocks = self::get_undeletable_block_types();
        $requiredbythemeblocks = $this->get_required_by_theme_block_types();
        $pageformat = $this->page->pagetype;
        foreach($allblocks as $block) {
            if (!$bi = block_instance($block->name)) {
                continue;
            }
            if ($block->visible && !in_array($block->name, $unaddableblocks) &&
                    !in_array($block->name, $requiredbythemeblocks) &&
                    ($bi->instance_allow_multiple() || !$this->is_block_present($block->name)) &&
                    blocks_name_allowed_in_format($block->name, $pageformat) &&
                    $bi->user_can_addto($this->page)) {
                $block->title = $bi->get_title();
                $this->addableblocks[$block->name] = $block;
            }
        }

        core_collator::asort_objects_by_property($this->addableblocks, 'title');
        return $this->addableblocks;
    }