Coverage Report

Created: 2026-01-10 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wt/src/Wt/WLink.C
Line
Count
Source
1
/*
2
 * Copyright (C) 2011 Emweb bv, Herent, Belgium.
3
 *
4
 * See the LICENSE file for terms of use.
5
 */
6
#include <Wt/WLink.h>
7
8
#include <Wt/WApplication.h>
9
#include <Wt/WEnvironment.h>
10
#include <Wt/WException.h>
11
#include <Wt/WInteractWidget.h>
12
#include <Wt/WResource.h>
13
#include <Wt/WString.h>
14
15
#include <boost/algorithm/string.hpp>
16
17
#include "WebSession.h"
18
19
namespace Wt {
20
21
WLink::WLink()
22
0
  : type_(LinkType::Url),
23
0
    target_(LinkTarget::Self)
24
0
{
25
#ifdef WT_TARGET_JAVA
26
  setUrl("");
27
#endif
28
0
}
29
30
WLink::WLink(const char *url)
31
0
  : target_(LinkTarget::Self)
32
0
{
33
0
  setUrl(url);
34
0
}
35
36
WLink::WLink(const std::string& url)
37
0
  : target_(LinkTarget::Self)
38
0
{
39
0
  setUrl(url);
40
0
}
41
42
WLink::WLink(LinkType type, const std::string& value)
43
0
  : target_(LinkTarget::Self)
44
0
{
45
0
  switch (type) {
46
0
  case LinkType::Url: setUrl(value); break;
47
0
  case LinkType::InternalPath: setInternalPath(WString::fromUTF8(value)); break;
48
0
  default:
49
0
    throw WException("WLink::WLink(type) cannot be used for a Resource");
50
0
  }
51
0
}
52
53
WLink::WLink(const std::shared_ptr<WResource>& resource)
54
0
  : target_(LinkTarget::Self)
55
0
{
56
0
  setResource(resource);
57
0
}
58
59
bool WLink::isNull() const
60
0
{
61
0
  return type_ == LinkType::Url && url().empty();
62
0
}
63
64
void WLink::setUrl(const std::string& url)
65
0
{
66
0
  type_ = LinkType::Url;
67
0
  stringValue_ = url;
68
0
  resource_.reset();
69
0
}
70
71
std::string WLink::url() const
72
0
{
73
0
  switch (type_) {
74
0
  case LinkType::Url:
75
0
    return stringValue_;
76
0
  case LinkType::Resource:
77
0
    return resource()->url();
78
0
  case LinkType::InternalPath:
79
0
    return WApplication::instance()->bookmarkUrl(internalPath().toUTF8());
80
0
  }
81
82
0
  return std::string();
83
0
}
84
85
void WLink::setResource(const std::shared_ptr<WResource>& resource)
86
0
{
87
0
  type_ = LinkType::Resource;
88
0
  resource_ = resource;
89
0
  stringValue_.clear();
90
0
}
91
92
std::shared_ptr<WResource> WLink::resource() const
93
0
{
94
0
  return resource_;
95
0
}
96
97
void WLink::setInternalPath(const WT_USTRING& internalPath)
98
0
{
99
0
  type_ = LinkType::InternalPath;
100
0
  std::string path = internalPath.toUTF8();
101
102
0
  if (boost::starts_with(path, "#/"))
103
0
    path = path.substr(1);
104
105
0
  stringValue_ = path;
106
0
  resource_.reset();
107
0
}
108
109
WT_USTRING WLink::internalPath() const
110
0
{
111
0
  if (type_ == LinkType::InternalPath) {
112
0
    return WT_USTRING::fromUTF8(stringValue_);
113
0
  } else {
114
0
#ifndef WT_TARGET_JAVA
115
0
    return WT_USTRING::Empty;
116
#else
117
    return std::string();
118
#endif
119
0
  }
120
0
}
121
122
void WLink::setTarget(LinkTarget target)
123
0
{
124
0
  target_ = target;
125
0
}
126
127
bool WLink::operator==(const WLink& other) const
128
0
{
129
0
  return type_ == other.type_ &&
130
0
    stringValue_ == other.stringValue_ &&
131
0
    resource_ == other.resource_;
132
0
}
133
134
bool WLink::operator!=(const WLink& other) const
135
0
{
136
0
  return !(*this == other);
137
0
}
138
139
std::string WLink::resolveUrl(WApplication *app) const
140
0
{
141
0
  std::string relativeUrl;
142
143
0
  switch (type_) {
144
0
  case LinkType::InternalPath: {
145
0
    if (app->environment().ajax())
146
0
      relativeUrl = app->bookmarkUrl(internalPath().toUTF8());
147
0
    else if (app->environment().treatLikeBot())
148
0
      relativeUrl = app->bookmarkUrl(internalPath().toUTF8());
149
0
    else
150
      // If no JavaScript is available, then we still add the session
151
      // so that when used in WAnchor it will be handled by the same
152
      // session.
153
0
      relativeUrl = app->session()->mostRelativeUrl(internalPath().toUTF8());
154
0
  }
155
0
    break;
156
0
  default:
157
0
    relativeUrl = url();
158
0
  }
159
160
0
  return app->resolveRelativeUrl(relativeUrl);
161
0
}
162
163
JSlot *WLink::manageInternalPathChange(WApplication *app,
164
                                       WInteractWidget *widget,
165
                                       JSlot *slot) const
166
0
{
167
0
  if (type_ == LinkType::InternalPath) {
168
0
    if (app->environment().ajax()) {
169
0
      if (!slot) {
170
0
        slot = new JSlot();
171
0
        widget->clicked().connect(*slot);
172
0
        widget->clicked().preventDefaultAction();
173
0
      }
174
175
0
      slot->setJavaScript
176
0
        ("function(){" +
177
0
         app->javaScriptClass() + "._p_.setHash("
178
0
         + WWebWidget::jsStringLiteral(internalPath()) + ",true);"
179
0
         "}");
180
181
#ifdef WT_TARGET_JAVA
182
      widget->clicked().senderRepaint();
183
#endif // WT_TARGET_JAVA
184
185
0
      return slot;
186
0
    }
187
0
  }
188
189
0
  delete slot;
190
191
0
  return 0;
192
0
}
193
194
}