1<?php 2 3 4namespace ComboStrap\Meta\Field; 5 6use ComboStrap\ExceptionCompile; 7use ComboStrap\LogUtility; 8use ComboStrap\MarkupPath; 9use ComboStrap\Meta\Api\Metadata; 10use ComboStrap\Meta\Api\MetadataInteger; 11use ComboStrap\Meta\Store\MetadataDbStore; 12use ComboStrap\Meta\Store\MetadataDokuWikiStore; 13use ComboStrap\Sqlite; 14 15/** 16 * Class BacklinkCount 17 * @package ComboStrap 18 * Internal backlink count 19 */ 20class BacklinkCount extends MetadataInteger 21{ 22 const PROPERTY_NAME = 'backlink_count'; 23 24 public static function createFromResource(MarkupPath $page) 25 { 26 return (new BacklinkCount()) 27 ->setResource($page); 28 } 29 30 static public function getDescription(): string 31 { 32 return "The number of backlinks"; 33 } 34 35 static public function getLabel(): string 36 { 37 return "Backlink Count"; 38 } 39 40 public static function getName(): string 41 { 42 return self::PROPERTY_NAME; 43 } 44 45 static public function getPersistenceType(): string 46 { 47 return Metadata::DERIVED_METADATA; 48 } 49 50 static public function isMutable(): bool 51 { 52 return false; 53 } 54 55 public function buildFromReadStore(): Metadata 56 { 57 58 $storeClass = get_class($this->getReadStore()); 59 switch ($storeClass) { 60 case MetadataDokuWikiStore::class: 61 $resource = $this->getResource(); 62 if (!($resource instanceof MarkupPath)) { 63 LogUtility::msg("Backlink count is not yet supported on the resource type ({$resource->getType()}"); 64 return $this; 65 } 66 $backlinks = $resource->getBacklinks(); 67 $this->value = sizeof($backlinks); 68 return $this; 69 case MetadataDbStore::class: 70 $this->value = $this->calculateBacklinkCount(); 71 return $this; 72 default: 73 LogUtility::msg("The store ($storeClass) does not support backlink count"); 74 return $this; 75 } 76 77 78 } 79 80 /** 81 * Sqlite is much quicker than the Dokuwiki Internal Index 82 * We use it every time that we can 83 * 84 * @return int|null 85 */ 86 private function calculateBacklinkCount(): ?int 87 { 88 89 $sqlite = Sqlite::createOrGetSqlite(); 90 /** @noinspection SqlResolve */ 91 $request = $sqlite 92 ->createRequest() 93 ->setQueryParametrized("select count(1) from PAGE_REFERENCES where REFERENCE = ? ", [$this->getResource()->getPathObject()->toAbsoluteId()]); 94 $count = 0; 95 try { 96 $count = $request 97 ->execute() 98 ->getFirstCellValue(); 99 } catch (ExceptionCompile $e) { 100 LogUtility::error($e->getMessage(), self::PROPERTY_NAME, $e); 101 } finally { 102 $request->close(); 103 } 104 return intval($count); 105 106 } 107 108 109 public function setFromStoreValueWithoutException($value): Metadata 110 { 111 /** 112 * not used because 113 * the data is not stored in the database 114 * We overwrite and build the value {@link BacklinkCount::buildFromReadStore()} 115 */ 116 return $this; 117 } 118 119 120} 121